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_namespaces_elementtree(self):
    2088          etree = self.etree
    2089          r = {None: 'http://ns.infrae.com/foo',
    2090               'hoi': 'http://ns.infrae.com/hoi'}
    2091          e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r)
    2092          tree = etree.ElementTree(element=e)
    2093          etree.SubElement(e, '{http://ns.infrae.com/hoi}x')
    2094          self.assertEqual(
    2095              _bytes('<z xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi"><hoi:x></hoi:x></z>'),
    2096              self._writeElement(e))
    2097
    2098 -    def test_namespaces_default_copy_element(self):
    2099          etree = self.etree
    2100
    2101          r = {None: 'http://ns.infrae.com/foo'}
    2102          e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2103          e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2104
    2105          e1.append(e2)
    2106
    2107          self.assertEqual(
    2108              None,
    2109              e1.prefix)
    2110          self.assertEqual(
    2111              None,
    2112              e1[0].prefix)
    2113          self.assertEqual(
    2114              '{http://ns.infrae.com/foo}bar',
    2115              e1.tag)
    2116          self.assertEqual(
    2117              '{http://ns.infrae.com/foo}bar',
    2118              e1[0].tag)
    2119
    2120 -    def test_namespaces_copy_element(self):
    2121          etree = self.etree
    2122
    2123          r = {None: 'http://ns.infrae.com/BAR'}
    2124          e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r)
    2125          e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2126
    2127          e1.append(e2)
    2128
    2129          self.assertEqual(
    2130              None,
    2131              e1.prefix)
    2132          self.assertNotEqual(
    2133              None,
    2134              e2.prefix)
    2135          self.assertEqual(
    2136              '{http://ns.infrae.com/BAR}bar',
    2137              e1.tag)
    2138          self.assertEqual(
    2139              '{http://ns.infrae.com/foo}bar',
    2140              e2.tag)
    2141
    2142 -    def test_namespaces_reuse_after_move(self):
    2143          ns_href = "http://a.b.c"
    2144          one = self.etree.fromstring(
    2145              _bytes('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
    2146          baz = one[0][0]
    2147
    2148          two = self.etree.fromstring(
    2149              _bytes('<root xmlns:ns="%s"/>' % ns_href))
    2150          two.append(baz)
    2151          del one # make sure the source document is deallocated
    2152
    2153          self.assertEqual('{%s}baz' % ns_href, baz.tag)
    2154          self.assertEqual(
    2155              _bytes('<root xmlns:ns="%s"><ns:baz/></root>' % ns_href),
    2156              self.etree.tostring(two))
    2157
    2158 -    def test_namespace_cleanup(self):
    2159          xml = _bytes('<foo xmlns="F" xmlns:x="x"><bar xmlns:ns="NS" xmlns:b="b" xmlns="B"><ns:baz/></bar></foo>')
    2160          root = self.etree.fromstring(xml)
    2161          self.assertEqual(xml,
    2162                            self.etree.tostring(root))
    2163          self.etree.cleanup_namespaces(root)
    2164          self.assertEqual(
    2165              _bytes('<foo xmlns="F"><bar xmlns:ns="NS" xmlns="B"><ns:baz/></bar></foo>'),
    2166              self.etree.tostring(root))
    2167
    2168 -    def test_element_nsmap(self):
    2169          etree = self.etree
    2170
    2171          r = {None: 'http://ns.infrae.com/foo',
    2172               'hoi': 'http://ns.infrae.com/hoi'}
    2173          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2174          self.assertEqual(
    2175              r,
    2176              e.nsmap)
    2177
    2178 -    def test_subelement_nsmap(self):
    2179          etree = self.etree
    2180
    2181          re = {None: 'http://ns.infrae.com/foo',
    2182               'hoi': 'http://ns.infrae.com/hoi'}
    2183          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re)
    2184
    2185          rs = {None: 'http://ns.infrae.com/honk',
    2186               'top': 'http://ns.infrae.com/top'}
    2187          s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs)
    2188
    2189          r = re.copy()
    2190          r.update(rs)
    2191          self.assertEqual(re, e.nsmap)
    2192          self.assertEqual(r,  s.nsmap)
    2193
    2194 -    def test_html_prefix_nsmap(self):
    2195          etree = self.etree
    2196          el = etree.HTML('<hha:page-description>aa</hha:page-description>').find('.//page-description')
    2197          self.assertEqual({'hha': None}, el.nsmap)
    2198
    2199 -    def test_getiterator_filter_multiple(self):
    2200          Element = self.etree.Element
    2201          SubElement = self.etree.SubElement
    2202
    2203          a = Element('a')
    2204          b = SubElement(a, 'b')
    2205          c = SubElement(a, 'c')
    2206          d = SubElement(b, 'd')
    2207          e = SubElement(c, 'e')
    2208          f = SubElement(c, 'f')
    2209
    2210          self.assertEqual(
    2211              [a, b],
    2212                 list(a.getiterator('a', 'b')))
    2213          self.assertEqual(
    2214              [],
    2215                list(a.getiterator('x', 'y')))
    2216          self.assertEqual(
    2217              [a, f],
    2218                list(a.getiterator('f', 'a')))
    2219          self.assertEqual(
    2220              [c, e, f],
    2221                 list(c.getiterator('c', '*', 'a')))
    2222          self.assertEqual(
    2223              [],
    2224                    list(a.getiterator( (), () )))
    2225
    2226 -    def test_getiterator_filter_multiple_tuple(self):
    2227          Element = self.etree.Element
    2228          SubElement = self.etree.SubElement
    2229
    2230          a = Element('a')
    2231          b = SubElement(a, 'b')
    2232          c = SubElement(a, 'c')
    2233          d = SubElement(b, 'd')
    2234          e = SubElement(c, 'e')
    2235          f = SubElement(c, 'f')
    2236
    2237          self.assertEqual(
    2238              [a, b],
    2239                    list(a.getiterator( ('a', 'b') )))
    2240          self.assertEqual(
    2241              [],
    2242                list(a.getiterator( ('x', 'y') )))
    2243          self.assertEqual(
    2244              [a, f],
    2245                    list(a.getiterator( ('f', 'a') )))
    2246          self.assertEqual(
    2247              [c, e, f],
    2248                       list(c.getiterator( ('c', '*', 'a') )))
    2249          self.assertEqual(
    2250              [],
    2251                list(a.getiterator( () )))
    2252
    2253 -    def test_getiterator_filter_namespace(self):
    2254          Element = self.etree.Element
    2255          SubElement = self.etree.SubElement
    2256
    2257          a = Element('{a}a')
    2258          b = SubElement(a, '{a}b')
    2259          c = SubElement(a, '{a}c')
    2260          d = SubElement(b, '{b}d')
    2261          e = SubElement(c, '{a}e')
    2262          f = SubElement(c, '{b}f')
    2263          g = SubElement(c, 'g')
    2264
    2265          self.assertEqual(
    2266              [a],
    2267              list(a.getiterator('{a}a')))
    2268          self.assertEqual(
    2269              [],
    2270              list(a.getiterator('{b}a')))
    2271          self.assertEqual(
    2272              [],
    2273              list(a.getiterator('a')))
    2274          self.assertEqual(
    2275              [a,b,d,c,e,f,g],
    2276              list(a.getiterator('*')))
    2277          self.assertEqual(
    2278              [f],
    2279              list(c.getiterator('{b}*')))
    2280          self.assertEqual(
    2281              [d, f],
    2282              list(a.getiterator('{b}*')))
    2283          self.assertEqual(
    2284              [g],
    2285              list(a.getiterator('g')))
    2286          self.assertEqual(
    2287              [g],
    2288              list(a.getiterator('{}g')))
    2289          self.assertEqual(
    2290              [g],
    2291              list(a.getiterator('{}*')))
    2292
    2293 -    def test_getiterator_filter_local_name(self):
    2294          Element = self.etree.Element
    2295          SubElement = self.etree.SubElement
    2296
    2297          a = Element('{a}a')
    2298          b = SubElement(a, '{nsA}b')
    2299          c = SubElement(b, '{nsB}b')
    2300          d = SubElement(a, 'b')
    2301          e = SubElement(a, '{nsA}e')
    2302          f = SubElement(e, '{nsB}e')
    2303          g = SubElement(e, 'e')
    2304
    2305          self.assertEqual(
    2306              [b, c, d],
    2307              list(a.getiterator('{*}b')))
    2308          self.assertEqual(
    2309              [e, f, g],
    2310              list(a.getiterator('{*}e')))
    2311          self.assertEqual(
    2312              [a, b, c, d, e, f, g],
    2313              list(a.getiterator('{*}*')))
    2314
    2315 -    def test_getiterator_filter_entities(self):
    2316          Element = self.etree.Element
    2317          Entity = self.etree.Entity
    2318          SubElement = self.etree.SubElement
    2319
    2320          a = Element('a')
    2321          b = SubElement(a, 'b')
    2322          entity_b = Entity("TEST-b")
    2323          b.append(entity_b)
    2324
    2325          self.assertEqual(
    2326              [entity_b],
    2327              list(a.getiterator(Entity)))
    2328
    2329          entity_a = Entity("TEST-a")
    2330          a.append(entity_a)
    2331
    2332          self.assertEqual(
    2333              [entity_b, entity_a],
    2334              list(a.getiterator(Entity)))
    2335
    2336          self.assertEqual(
    2337              [entity_b],
    2338              list(b.getiterator(Entity)))
    2339
    2340 -    def test_getiterator_filter_element(self):
    2341          Element = self.etree.Element
    2342          Comment = self.etree.Comment
    2343          PI = self.etree.PI
    2344          SubElement = self.etree.SubElement
    2345
    2346          a = Element('a')
    2347          b = SubElement(a, 'b')
    2348          a.append(Comment("test"))
    2349          a.append(PI("pi", "content"))
    2350          c = SubElement(a, 'c')
    2351
    2352          self.assertEqual(
    2353              [a, b, c],
    2354              list(a.getiterator(Element)))
    2355
    2356 -    def test_getiterator_filter_all_comment_pi(self):
    2357          # ElementTree iterates over everything here
    2358          Element = self.etree.Element
    2359          Comment = self.etree.Comment
    2360          PI = self.etree.PI
    2361          SubElement = self.etree.SubElement
    2362
    2363          a = Element('a')
    2364          b = SubElement(a, 'b')
    2365          a.append(Comment("test"))
    2366          a.append(PI("pi", "content"))
    2367          c = SubElement(a, 'c')
    2368
    2369          self.assertEqual(
    2370              [a, b, c],
    2371              list(a.getiterator('*')))
    2372
    2373 -    def test_elementtree_find_qname(self):
    2374          XML = self.etree.XML
    2375          ElementTree = self.etree.ElementTree
    2376          QName = self.etree.QName
    2377          tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
    2378          self.assertEqual(tree.find(QName("c")), tree.getroot()[2])
    2379
    2380 -    def test_elementtree_findall_qname(self):
    2381          XML = self.etree.XML
    2382          ElementTree = self.etree.ElementTree
    2383          QName = self.etree.QName
    2384          tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
    2385          self.assertEqual(len(list(tree.findall(QName("c")))), 1)
    2386
    2387 -    def test_elementtree_findall_ns_qname(self):
    2388          XML = self.etree.XML
    2389          ElementTree = self.etree.ElementTree
    2390          QName = self.etree.QName
    2391          tree = ElementTree(XML(
    2392                  _bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>')))
    2393          self.assertEqual(len(list(tree.findall(QName("b")))), 2)
    2394          self.assertEqual(len(list(tree.findall(QName("X", "b")))), 1)
    2395
    2396 -    def test_findall_ns(self):
    2397          XML = self.etree.XML
    2398          root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
    2399          self.assertEqual(len(root.findall(".//{X}b")), 2)
    2400          self.assertEqual(len(root.findall(".//{X}*")), 2)
    2401          self.assertEqual(len(root.findall(".//b")), 3)
    2402
    2403 -    def test_findall_different_nsmaps(self):
    2404          XML = self.etree.XML
    2405          root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>'))
    2406          nsmap = {'xx': 'X'}
    2407          self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2)
    2408          self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 2)
    2409          self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
    2410          nsmap = {'xx': 'Y'}
    2411          self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 1)
    2412          self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 1)
    2413          self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
    2414
    2415 -    def test_findall_different_nsmaps(self):
    2416          XML = self.etree.XML
    2417          root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>'))
    2418          nsmap = {'xx': 'X'}
    2419          self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2)
    2420          self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 2)
    2421          self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
    2422          nsmap = {'xx': 'Y'}
    2423          self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 1)
    2424          self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 1)
    2425          self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
    2426
    2427 -    def test_findall_syntax_error(self):
    2428          XML = self.etree.XML
    2429          root = XML(_bytes('<a><b><c/></b><b/><c><b/><b/></c><b/></a>'))
    2430          self.assertRaises(SyntaxError, root.findall, '')
    2431          self.assertRaises(SyntaxError, root.findall, '//')  # absolute path on Element
    2432          self.assertRaises(SyntaxError, root.findall, './//')
    2433
    2434 -    def test_index(self):
    2435          etree = self.etree
    2436          e = etree.Element('foo')
    2437          for i in range(10):
    2438              etree.SubElement(e, 'a%s' % i)
    2439          for i in range(10):
    2440              self.assertEqual(
    2441                  i,
    2442                  e.index(e[i]))
    2443          self.assertEqual(
    2444              3, e.index(e[3], 3))
    2445          self.assertRaises(
    2446              ValueError, e.index, e[3], 4)
    2447          self.assertRaises(
    2448              ValueError, e.index, e[3], 0, 2)
    2449          self.assertRaises(
    2450              ValueError, e.index, e[8], 0, -3)
    2451          self.assertRaises(
    2452              ValueError, e.index, e[8], -5, -3)
    2453          self.assertEqual(
    2454              8, e.index(e[8], 0, -1))
    2455          self.assertEqual(
    2456              8, e.index(e[8], -12, -1))
    2457          self.assertEqual(
    2458              0, e.index(e[0], -12, -1))
    2459
    2460 -    def test_replace(self):
    2461          etree = self.etree
    2462          e = etree.Element('foo')
    2463          for i in range(10):
    2464              el = etree.SubElement(e, 'a%s' % i)
    2465              el.text = "text%d" % i
    2466              el.tail = "tail%d" % i
    2467
    2468          child0 = e[0]
    2469          child1 = e[1]
    2470          child2 = e[2]
    2471
    2472          e.replace(e[0], e[1])
    2473          self.assertEqual(
    2474              9, len(e))
    2475          self.assertEqual(
    2476              child1, e[0])
    2477          self.assertEqual(
    2478              child1.text, "text1")
    2479          self.assertEqual(
    2480              child1.tail, "tail1")
    2481          self.assertEqual(
    2482              child0.tail, "tail0")
    2483          self.assertEqual(
    2484              child2, e[1])
    2485
    2486          e.replace(e[-1], e[0])
    2487          self.assertEqual(
    2488              child1, e[-1])
    2489          self.assertEqual(
    2490              child1.text, "text1")
    2491          self.assertEqual(
    2492              child1.tail, "tail1")
    2493          self.assertEqual(
    2494              child2, e[0])
    2495
    2496 -    def test_replace_new(self):
    2497          etree = self.etree
    2498          e = etree.Element('foo')
    2499          for i in range(10):
    2500              etree.SubElement(e, 'a%s' % i)
    2501
    2502          new_element = etree.Element("test")
    2503          new_element.text = "TESTTEXT"
    2504          new_element.tail = "TESTTAIL"
    2505          child1 = e[1]
    2506          e.replace(e[0], new_element)
    2507          self.assertEqual(
    2508              new_element, e[0])
    2509          self.assertEqual(
    2510              "TESTTEXT",
    2511              e[0].text)
    2512          self.assertEqual(
    2513              "TESTTAIL",
    2514              e[0].tail)
    2515          self.assertEqual(
    2516              child1, e[1])
    2517
    2518 -    def test_setslice_all_empty_reversed(self):
    2519          Element = self.etree.Element
    2520          SubElement = self.etree.SubElement
    2521
    2522          a = Element('a')
    2523
    2524          e = Element('e')
    2525          f = Element('f')
    2526          g = Element('g')
    2527
    2528          s = [e, f, g]
    2529          a[::-1] = s
    2530          self.assertEqual(
    2531              [g, f, e],
    2532              list(a))
    2533
    2534 -    def test_setslice_step(self):
    2535          Element = self.etree.Element
    2536          SubElement = self.etree.SubElement
    2537
    2538          a = Element('a')
    2539          b = SubElement(a, 'b')
    2540          c = SubElement(a, 'c')
    2541          d = SubElement(a, 'd')
    2542          e = SubElement(a, 'e')
    2543
    2544          x = Element('x')
    2545          y = Element('y')
    2546
    2547          a[1::2] = [x, y]
    2548          self.assertEqual(
    2549              [b, x, d, y],
    2550              list(a))
    2551
    2552 -    def test_setslice_step_negative(self):
    2553          Element = self.etree.Element
    2554          SubElement = self.etree.SubElement
    2555
    2556          a = Element('a')
    2557          b = SubElement(a, 'b')
    2558          c = SubElement(a, 'c')
    2559          d = SubElement(a, 'd')
    2560          e = SubElement(a, 'e')
    2561
    2562          x = Element('x')
    2563          y = Element('y')
    2564
    2565          a[1::-1] = [x, y]
    2566          self.assertEqual(
    2567              [y, x, d, e],
    2568              list(a))
    2569
    2570 -    def test_setslice_step_negative2(self):
    2571          Element = self.etree.Element
    2572          SubElement = self.etree.SubElement
    2573
    2574          a = Element('a')
    2575          b = SubElement(a, 'b')
    2576          c = SubElement(a, 'c')
    2577          d = SubElement(a, 'd')
    2578          e = SubElement(a, 'e')
    2579
    2580          x = Element('x')
    2581          y = Element('y')
    2582
    2583          a[::-2] = [x, y]
    2584          self.assertEqual(
    2585              [b, y, d, x],
    2586              list(a))
    2587
    2588 -    def test_setslice_step_overrun(self):
    2589          Element = self.etree.Element
    2590          SubElement = self.etree.SubElement
    2591          try:
    2592              slice
    2593          except NameError:
    2594              print("slice() not found")
    2595              return
    2596
    2597          a = Element('a')
    2598          b = SubElement(a, 'b')
    2599          c = SubElement(a, 'c')
    2600          d = SubElement(a, 'd')
    2601          e = SubElement(a, 'e')
    2602
    2603          x = Element('x')
    2604          y = Element('y')
    2605          z = Element('z')
    2606
    2607          self.assertRaises(
    2608              ValueError,
    2609              operator.setitem, a, slice(1,None,2), [x, y, z])
    2610
    2611          self.assertEqual(
    2612              [b, c, d, e],
    2613              list(a))
    2614
    2615 -    def test_sourceline_XML(self):
    2616          XML = self.etree.XML
    2617          root = XML(_bytes('''<?xml version="1.0"?>
    2618          <root><test>
    2619
    2620          <bla/></test>
    2621          </root>
    2622          '''))
    2623
    2624          self.assertEqual(
    2625              [2, 2, 4],
    2626              [ el.sourceline for el in root.getiterator() ])
    2627
    2628 -    def test_sourceline_parse(self):
    2629          parse = self.etree.parse
    2630          tree = parse(fileInTestDir('include/test_xinclude.xml'))
    2631
    2632          self.assertEqual(
    2633              [1, 2, 3],
    2634              [ el.sourceline for el in tree.getiterator() ])
    2635
    2636 -    def test_sourceline_iterparse_end(self):
    2637          iterparse = self.etree.iterparse
    2638          lines = [ el.sourceline for (event, el) in
    2639                    iterparse(fileInTestDir('include/test_xinclude.xml')) ]
    2640
    2641          self.assertEqual(
    2642              [2, 3, 1],
    2643              lines)
    2644
    2645 -    def test_sourceline_iterparse_start(self):
    2646          iterparse = self.etree.iterparse
    2647          lines = [ el.sourceline for (event, el) in
    2648                    iterparse(fileInTestDir('include/test_xinclude.xml'),
    2649                              events=("start",)) ]
    2650
    2651          self.assertEqual(
    2652              [1, 2, 3],
    2653              lines)
    2654
    2655 -    def test_sourceline_element(self):
    2656          Element = self.etree.Element
    2657          SubElement = self.etree.SubElement
    2658          el = Element("test")
    2659          self.assertEqual(None, el.sourceline)
    2660
    2661          child = SubElement(el, "test")
    2662          self.assertEqual(None, el.sourceline)
    2663          self.assertEqual(None, child.sourceline)
    2664
    2665 -    def test_XML_base_url_docinfo(self):
    2666          etree = self.etree
    2667          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    2668          docinfo = root.getroottree().docinfo
    2669          self.assertEqual(docinfo.URL, "http://no/such/url")
    2670
    2671 -    def test_XML_set_base_url_docinfo(self):
    2672          etree = self.etree
    2673          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    2674          docinfo = root.getroottree().docinfo
    2675          self.assertEqual(docinfo.URL, "http://no/such/url")
    2676          docinfo.URL = "https://secret/url"
    2677          self.assertEqual(docinfo.URL, "https://secret/url")
    2678
    2679 -    def test_parse_stringio_base_url(self):
    2680          etree = self.etree
    2681          tree = etree.parse(BytesIO("<root/>"), base_url="http://no/such/url")
    2682          docinfo = tree.docinfo
    2683          self.assertEqual(docinfo.URL, "http://no/such/url")
    2684
    2685 -    def test_parse_base_url_docinfo(self):
    2686          etree = self.etree
    2687          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
    2688                             base_url="http://no/such/url")
    2689          docinfo = tree.docinfo
    2690          self.assertEqual(docinfo.URL, "http://no/such/url")
    2691
    2692 -    def test_HTML_base_url_docinfo(self):
    2693          etree = self.etree
    2694          root = etree.HTML(_bytes("<html/>"), base_url="http://no/such/url")
    2695          docinfo = root.getroottree().docinfo
    2696          self.assertEqual(docinfo.URL, "http://no/such/url")
    2697
    2698 -    def test_docinfo_public(self):
    2699          etree = self.etree
    2700          xml_header = '<?xml version="1.0" encoding="ascii"?>'
    2701          pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
    2702          sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    2703          doctype_string = '<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id)
    2704
    2705          xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
    2706
    2707          tree = etree.parse(BytesIO(xml))
    2708          docinfo = tree.docinfo
    2709          self.assertEqual(docinfo.encoding,    "ascii")
    2710          self.assertEqual(docinfo.xml_version, "1.0")
    2711          self.assertEqual(docinfo.public_id,   pub_id)
    2712          self.assertEqual(docinfo.system_url,  sys_id)
    2713          self.assertEqual(docinfo.root_name,   'html')
    2714          self.assertEqual(docinfo.doctype, doctype_string)
    2715
    2716 -    def test_docinfo_system(self):
    2717          etree = self.etree
    2718          xml_header = '<?xml version="1.0" encoding="UTF-8"?>'
    2719          sys_id = "some.dtd"
    2720          doctype_string = '<!DOCTYPE html SYSTEM "%s">' % sys_id
    2721          xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
    2722
    2723          tree = etree.parse(BytesIO(xml))
    2724          docinfo = tree.docinfo
    2725          self.assertEqual(docinfo.encoding,    "UTF-8")
    2726          self.assertEqual(docinfo.xml_version, "1.0")
    2727          self.assertEqual(docinfo.public_id,   None)
    2728          self.assertEqual(docinfo.system_url,  sys_id)
    2729          self.assertEqual(docinfo.root_name,   'html')
    2730          self.assertEqual(docinfo.doctype, doctype_string)
    2731
    2732 -    def test_docinfo_empty(self):
    2733          etree = self.etree
    2734          xml = _bytes('<html><body></body></html>')
    2735          tree = etree.parse(BytesIO(xml))
    2736          docinfo = tree.docinfo
    2737          self.assertEqual(docinfo.encoding,    "UTF-8")
    2738          self.assertEqual(docinfo.xml_version, "1.0")
    2739          self.assertEqual(docinfo.public_id,   None)
    2740          self.assertEqual(docinfo.system_url,  None)
    2741          self.assertEqual(docinfo.root_name,   'html')
    2742          self.assertEqual(docinfo.doctype, '')
    2743
    2744 -    def test_docinfo_name_only(self):
    2745          etree = self.etree
    2746          xml = _bytes('<!DOCTYPE root><root></root>')
    2747          tree = etree.parse(BytesIO(xml))
    2748          docinfo = tree.docinfo
    2749          self.assertEqual(docinfo.encoding,    "UTF-8")
    2750          self.assertEqual(docinfo.xml_version, "1.0")
    2751          self.assertEqual(docinfo.public_id,   None)
    2752          self.assertEqual(docinfo.system_url,  None)
    2753          self.assertEqual(docinfo.root_name,   'root')
    2754          self.assertEqual(docinfo.doctype, '<!DOCTYPE root>')
    2755
    2756 -    def test_doctype_name_only_roundtrip(self):
    2757          etree = self.etree
    2758          xml = _bytes('<!DOCTYPE root>\n<root/>')
    2759          tree = etree.parse(BytesIO(xml))
    2760          self.assertEqual(xml, etree.tostring(tree))
    2761
    2762 -    def test_doctype_output_override(self):
    2763          etree = self.etree
    2764          pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
    2765          sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    2766          doctype_string = _bytes('<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id))
    2767
    2768          xml = _bytes('<!DOCTYPE root>\n<root/>')
    2769          tree = etree.parse(BytesIO(xml))
    2770          self.assertEqual(xml.replace(_bytes('<!DOCTYPE root>'), doctype_string),
    2771                            etree.tostring(tree, doctype=doctype_string))
    2772
    2773 -    def test_xml_base(self):
    2774          etree = self.etree
    2775          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    2776          self.assertEqual(root.base, "http://no/such/url")
    2777          self.assertEqual(
    2778              root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
    2779          root.base = "https://secret/url"
    2780          self.assertEqual(root.base, "https://secret/url")
    2781          self.assertEqual(
    2782              root.get('{http://www.w3.org/XML/1998/namespace}base'),
    2783              "https://secret/url")
    2784
    2785 -    def test_xml_base_attribute(self):
    2786          etree = self.etree
    2787          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    2788          self.assertEqual(root.base, "http://no/such/url")
    2789          self.assertEqual(
    2790              root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
    2791          root.set('{http://www.w3.org/XML/1998/namespace}base',
    2792                   "https://secret/url")
    2793          self.assertEqual(root.base, "https://secret/url")
    2794          self.assertEqual(
    2795              root.get('{http://www.w3.org/XML/1998/namespace}base'),
    2796              "https://secret/url")
    2797
    2798 -    def test_html_base(self):
    2799          etree = self.etree
    2800          root = etree.HTML(_bytes("<html><body></body></html>"),
    2801                            base_url="http://no/such/url")
    2802          self.assertEqual(root.base, "http://no/such/url")
    2803
    2804 -    def test_html_base_tag(self):
    2805          etree = self.etree
    2806          root = etree.HTML(_bytes('<html><head><base href="http://no/such/url"></head></html>'))
    2807          self.assertEqual(root.base, "http://no/such/url")
    2808
    2809 -    def test_parse_fileobject_unicode(self):
    2810          # parse from a file object that returns unicode strings
    2811          f = LargeFileLikeUnicode()
    2812          tree = self.etree.parse(f)
    2813          root = tree.getroot()
    2814          self.assertTrue(root.tag.endswith('root'))
    2815
    2816 -    def test_dtd_io(self):
    2817          # check that DTDs that go in also go back out
    2818          xml = _bytes('''\
    2819          <!DOCTYPE test SYSTEM "test.dtd" [
    2820            <!ENTITY entity "tasty">
    2821            <!ELEMENT test (a)>
    2822            <!ELEMENT a (#PCDATA)>
    2823          ]>
    2824          <test><a>test-test</a></test>\
    2825          ''')
    2826          tree = self.etree.parse(BytesIO(xml))
    2827          self.assertEqual(self.etree.tostring(tree).replace(_bytes(" "), _bytes("")),
    2828                           xml.replace(_bytes(" "), _bytes("")))
    2829
    2830 -    def test_byte_zero(self):
    2831          Element = self.etree.Element
    2832
    2833          a = Element('a')
    2834          self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho')
    2835          self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho')
    2836
    2837          self.assertRaises(ValueError, Element, 'ha\0ho')
    2838
    2839 -    def test_unicode_byte_zero(self):
    2840          Element = self.etree.Element
    2841
    2842          a = Element('a')
    2843          self.assertRaises(ValueError, setattr, a, "text",
    2844                            _str('ha\0ho'))
    2845          self.assertRaises(ValueError, setattr, a, "tail",
    2846                            _str('ha\0ho'))
    2847
    2848          self.assertRaises(ValueError, Element,
    2849                            _str('ha\0ho'))
    2850
    2851 -    def test_byte_invalid(self):
    2852          Element = self.etree.Element
    2853
    2854          a = Element('a')
    2855          self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho')
    2856          self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho')
    2857
    2858          self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho')
    2859          self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho')
    2860
    2861          self.assertRaises(ValueError, Element, 'ha\x07ho')
    2862          self.assertRaises(ValueError, Element, 'ha\x02ho')
    2863
    2864 -    def test_unicode_byte_invalid(self):
    2865          Element = self.etree.Element
    2866
    2867          a = Element('a')
    2868          self.assertRaises(ValueError, setattr, a, "text",
    2869                            _str('ha\x07ho'))
    2870          self.assertRaises(ValueError, setattr, a, "text",
    2871                            _str('ha\x02ho'))
    2872
    2873          self.assertRaises(ValueError, setattr, a, "tail",
    2874                            _str('ha\x07ho'))
    2875          self.assertRaises(ValueError, setattr, a, "tail",
    2876                            _str('ha\x02ho'))
    2877
    2878          self.assertRaises(ValueError, Element,
    2879                            _str('ha\x07ho'))
    2880          self.assertRaises(ValueError, Element,
    2881                            _str('ha\x02ho'))
    2882
    2883 -    def test_unicode_byte_invalid_sequence(self):
    2884          Element = self.etree.Element
    2885
    2886          a = Element('a')
    2887          self.assertRaises(ValueError, setattr, a, "text",
    2888                            _str('ha\u1234\x07ho'))
    2889          self.assertRaises(ValueError, setattr, a, "text",
    2890                            _str('ha\u1234\x02ho'))
    2891
    2892          self.assertRaises(ValueError, setattr, a, "tail",
    2893                            _str('ha\u1234\x07ho'))
    2894          self.assertRaises(ValueError, setattr, a, "tail",
    2895                            _str('ha\u1234\x02ho'))
    2896
    2897          self.assertRaises(ValueError, Element,
    2898                            _str('ha\u1234\x07ho'))
    2899          self.assertRaises(ValueError, Element,
    2900                            _str('ha\u1234\x02ho'))
    2901
    2902 -    def test_encoding_tostring_utf16(self):
    2903          # ElementTree fails to serialize this
    2904          tostring = self.etree.tostring
    2905          Element = self.etree.Element
    2906          SubElement = self.etree.SubElement
    2907
    2908          a = Element('a')
    2909          b = SubElement(a, 'b')
    2910          c = SubElement(a, 'c')
    2911
    2912          result = tostring(a, encoding='UTF-16')
    2913          self.assertEqual(_bytes('<a><b></b><c></c></a>'),
    2914                            canonicalize(result))
    2915
    2916 -    def test_tostring_none(self):
    2917          # ElementTree raises an AssertionError here
    2918          tostring = self.etree.tostring
    2919          self.assertRaises(TypeError, self.etree.tostring, None)
    2920
    2921 -    def test_tostring_pretty(self):
    2922          tostring = self.etree.tostring
    2923          Element = self.etree.Element
    2924          SubElement = self.etree.SubElement
    2925
    2926          a = Element('a')
    2927          b = SubElement(a, 'b')
    2928          c = SubElement(a, 'c')
    2929
    2930          result = tostring(a)
    2931          self.assertEqual(result, _bytes("<a><b/><c/></a>"))
    2932
    2933          result = tostring(a, pretty_print=False)
    2934          self.assertEqual(result, _bytes("<a><b/><c/></a>"))
    2935
    2936          result = tostring(a, pretty_print=True)
    2937          self.assertEqual(result, _bytes("<a>\n  <b/>\n  <c/>\n</a>\n"))
    2938
    2939 -    def test_tostring_with_tail(self):
    2940          tostring = self.etree.tostring
    2941          Element = self.etree.Element
    2942          SubElement = self.etree.SubElement
    2943
    2944          a = Element('a')
    2945          a.tail = "aTAIL"
    2946          b = SubElement(a, 'b')
    2947          b.tail = "bTAIL"
    2948          c = SubElement(a, 'c')
    2949
    2950          result = tostring(a)
    2951          self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
    2952
    2953          result = tostring(a, with_tail=False)
    2954          self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>"))
    2955
    2956          result = tostring(a, with_tail=True)
    2957          self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
    2958
    2959 -    def test_standalone(self):
    2960          tostring = self.etree.tostring
    2961          XML = self.etree.XML
    2962          ElementTree = self.etree.ElementTree
    2963          Element = self.etree.Element
    2964
    2965          tree = Element("root").getroottree()
    2966          self.assertEqual(None, tree.docinfo.standalone)
    2967
    2968          tree = XML(_bytes("<root/>")).getroottree()
    2969          self.assertEqual(None, tree.docinfo.standalone)
    2970
    2971          tree = XML(_bytes(
    2972              "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"
    2973              )).getroottree()
    2974          self.assertEqual(True, tree.docinfo.standalone)
    2975
    2976          tree = XML(_bytes(
    2977              "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"
    2978              )).getroottree()
    2979          self.assertEqual(False, tree.docinfo.standalone)
    2980
    2981 -    def test_tostring_standalone(self):
    2982          tostring = self.etree.tostring
    2983          XML = self.etree.XML
    2984          ElementTree = self.etree.ElementTree
    2985
    2986          root = XML(_bytes("<root/>"))
    2987
    2988          tree = ElementTree(root)
    2989          self.assertEqual(None, tree.docinfo.standalone)
    2990
    2991          result = tostring(root, xml_declaration=True, encoding="ASCII")
    2992          self.assertEqual(result, _bytes(
    2993              "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
    2994
    2995          result = tostring(root, xml_declaration=True, encoding="ASCII",
    2996                            standalone=True)
    2997          self.assertEqual(result, _bytes(
    2998              "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
    2999
    3000          tree = ElementTree(XML(result))
    3001          self.assertEqual(True, tree.docinfo.standalone)
    3002
    3003          result = tostring(root, xml_declaration=True, encoding="ASCII",
    3004                            standalone=False)
    3005          self.assertEqual(result, _bytes(
    3006              "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"))
    3007
    3008          tree = ElementTree(XML(result))
    3009          self.assertEqual(False, tree.docinfo.standalone)
    3010
    3011 -    def test_tostring_standalone_in_out(self):
    3012          tostring = self.etree.tostring
    3013          XML = self.etree.XML
    3014          ElementTree = self.etree.ElementTree
    3015
    3016          root = XML(_bytes(
    3017              "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n<root/>"))
    3018
    3019          tree = ElementTree(root)
    3020          self.assertEqual(True, tree.docinfo.standalone)
    3021
    3022          result = tostring(root, xml_declaration=True, encoding="ASCII")
    3023          self.assertEqual(result, _bytes(
    3024              "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
    3025
    3026          result = tostring(root, xml_declaration=True, encoding="ASCII",
    3027                            standalone=True)
    3028          self.assertEqual(result, _bytes(
    3029              "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
    3030
    3031 -    def test_tostring_method_text_encoding(self):
    3032          tostring = self.etree.tostring
    3033          Element = self.etree.Element
    3034          SubElement = self.etree.SubElement
    3035
    3036          a = Element('a')
    3037          a.text = "A"
    3038          a.tail = "tail"
    3039          b = SubElement(a, 'b')
    3040          b.text = "B"
    3041          b.tail = _str("Søk på nettet")
    3042          c = SubElement(a, 'c')
    3043          c.text = "C"
    3044
    3045          result = tostring(a, method="text", encoding="UTF-16")
    3046
    3047          self.assertEqual(_str('ABSøk på nettetCtail').encode("UTF-16"),
    3048                            result)
    3049
    3050 -    def test_tostring_method_text_unicode(self):
    3051          tostring = self.etree.tostring
    3052          Element = self.etree.Element
    3053          SubElement = self.etree.SubElement
    3054
    3055          a = Element('a')
    3056          a.text = _str('Søk på nettetA')
    3057          a.tail = "tail"
    3058          b = SubElement(a, 'b')
    3059          b.text = "B"
    3060          b.tail = _str('Søk på nettetB')
    3061          c = SubElement(a, 'c')
    3062          c.text = "C"
    3063
    3064          self.assertRaises(UnicodeEncodeError,
    3065                            tostring, a, method="text")
    3066
    3067          self.assertEqual(
    3068              _str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'),
    3069              tostring(a, encoding="UTF-8", method="text"))
    3070
    3071 -    def test_tounicode(self):
    3072          tounicode = self.etree.tounicode
    3073          Element = self.etree.Element
    3074          SubElement = self.etree.SubElement
    3075
    3076          a = Element('a')
    3077          b = SubElement(a, 'b')
    3078          c = SubElement(a, 'c')
    3079
    3080          self.assertTrue(isinstance(tounicode(a), _unicode))
    3081          self.assertEqual(_bytes('<a><b></b><c></c></a>'),
    3082                            canonicalize(tounicode(a)))
    3083
    3084 -    def test_tounicode_element(self):
    3085          tounicode = self.etree.tounicode
    3086          Element = self.etree.Element
    3087          SubElement = self.etree.SubElement
    3088
    3089          a = Element('a')
    3090          b = SubElement(a, 'b')
    3091          c = SubElement(a, 'c')
    3092          d = SubElement(c, 'd')
    3093          self.assertTrue(isinstance(tounicode(b), _unicode))
    3094          self.assertTrue(isinstance(tounicode(c), _unicode))
    3095          self.assertEqual(_bytes('<b></b>'),
    3096                            canonicalize(tounicode(b)))
    3097          self.assertEqual(_bytes('<c><d></d></c>'),
    3098                            canonicalize(tounicode(c)))
    3099
    3100 -    def test_tounicode_none(self):
    3101          tounicode = self.etree.tounicode
    3102          self.assertRaises(TypeError, self.etree.tounicode, None)
    3103
    3104 -    def test_tounicode_element_tail(self):
    3105          tounicode = self.etree.tounicode
    3106          Element = self.etree.Element
    3107          SubElement = self.etree.SubElement
    3108
    3109          a = Element('a')
    3110          b = SubElement(a, 'b')
    3111          c = SubElement(a, 'c')
    3112          d = SubElement(c, 'd')
    3113          b.tail = 'Foo'
    3114
    3115          self.assertTrue(isinstance(tounicode(b), _unicode))
    3116          self.assertTrue(tounicode(b) == '<b/>Foo' or
    3117                       tounicode(b) == '<b />Foo')
    3118
    3119 -    def test_tounicode_pretty(self):
    3120          tounicode = self.etree.tounicode
    3121          Element = self.etree.Element
    3122          SubElement = self.etree.SubElement
    3123
    3124          a = Element('a')
    3125          b = SubElement(a, 'b')
    3126          c = SubElement(a, 'c')
    3127
    3128          result = tounicode(a)
    3129          self.assertEqual(result, "<a><b/><c/></a>")
    3130
    3131          result = tounicode(a, pretty_print=False)
    3132          self.assertEqual(result, "<a><b/><c/></a>")
    3133
    3134          result = tounicode(a, pretty_print=True)
    3135          self.assertEqual(result, "<a>\n  <b/>\n  <c/>\n</a>\n")
    3136
    3137 -    def test_tostring_unicode(self):
    3138          tostring = self.etree.tostring
    3139          Element = self.etree.Element
    3140          SubElement = self.etree.SubElement
    3141
    3142          a = Element('a')
    3143          b = SubElement(a, 'b')
    3144          c = SubElement(a, 'c')
    3145
    3146          self.assertTrue(isinstance(tostring(a, encoding=_unicode), _unicode))
    3147          self.assertEqual(_bytes('<a><b></b><c></c></a>'),
    3148                            canonicalize(tostring(a, encoding=_unicode)))
    3149
    3150 -    def test_tostring_unicode_element(self):
    3151          tostring = self.etree.tostring
    3152          Element = self.etree.Element
    3153          SubElement = self.etree.SubElement
    3154
    3155          a = Element('a')
    3156          b = SubElement(a, 'b')
    3157          c = SubElement(a, 'c')
    3158          d = SubElement(c, 'd')
    3159          self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode))
    3160          self.assertTrue(isinstance(tostring(c, encoding=_unicode), _unicode))
    3161          self.assertEqual(_bytes('<b></b>'),
    3162                            canonicalize(tostring(b, encoding=_unicode)))
    3163          self.assertEqual(_bytes('<c><d></d></c>'),
    3164                            canonicalize(tostring(c, encoding=_unicode)))
    3165
    3166 -    def test_tostring_unicode_none(self):
    3167          tostring = self.etree.tostring
    3168          self.assertRaises(TypeError, self.etree.tostring,
    3169                            None, encoding=_unicode)
    3170
    3171 -    def test_tostring_unicode_element_tail(self):
    3172          tostring = self.etree.tostring
    3173          Element = self.etree.Element
    3174          SubElement = self.etree.SubElement
    3175
    3176          a = Element('a')
    3177          b = SubElement(a, 'b')
    3178          c = SubElement(a, 'c')
    3179          d = SubElement(c, 'd')
    3180          b.tail = 'Foo'
    3181
    3182          self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode))
    3183          self.assertTrue(tostring(b, encoding=_unicode) == '<b/>Foo' or
    3184                       tostring(b, encoding=_unicode) == '<b />Foo')
    3185
    3186 -    def test_tostring_unicode_pretty(self):
    3187          tostring = self.etree.tostring
    3188          Element = self.etree.Element
    3189          SubElement = self.etree.SubElement
    3190
    3191          a = Element('a')
    3192          b = SubElement(a, 'b')
    3193          c = SubElement(a, 'c')
    3194
    3195          result = tostring(a, encoding=_unicode)
    3196          self.assertEqual(result, "<a><b/><c/></a>")
    3197
    3198          result = tostring(a, encoding=_unicode, pretty_print=False)
    3199          self.assertEqual(result, "<a><b/><c/></a>")
    3200
    3201          result = tostring(a, encoding=_unicode, pretty_print=True)
    3202          self.assertEqual(result, "<a>\n  <b/>\n  <c/>\n</a>\n")
    3203
    3204 -    def test_pypy_proxy_collect(self):
    3205          root = etree.Element('parent')
    3206          etree.SubElement(root, 'child')
    3207
    3208          self.assertEqual(len(root), 1)
    3209          self.assertEqual(root[0].tag, 'child')
    3210
    3211          # in PyPy, GC used to kill the Python proxy instance without cleanup
    3212          gc.collect()
    3213          self.assertEqual(len(root), 1)
    3214          self.assertEqual(root[0].tag, 'child')
    3215
    3216      # helper methods
    3217
    3218 -    def _writeElement(self, element, encoding='us-ascii', compression=0):
    3219          """Write out element for comparison.
    3220          """
    3221          ElementTree = self.etree.ElementTree
    3222          f = BytesIO()
    3223          tree = ElementTree(element=element)
    3224          tree.write(f, encoding=encoding, compression=compression)
    3225          data = f.getvalue()
    3226          if compression:
    3227              data = zlib.decompress(data)
    3228          return canonicalize(data)
    3229
    3230
    3231 -class _XIncludeTestCase(HelperTestCase):
    3232 -    def test_xinclude_text(self):
    3233          filename = fileInTestDir('test_broken.xml')
    3234          root = etree.XML(_bytes('''\
    3235          <doc xmlns:xi="http://www.w3.org/2001/XInclude">
    3236            <xi:include href="%s" parse="text"/>
    3237          </doc>
    3238          ''' % filename))
    3239          old_text = root.text
    3240          content = read_file(filename)
    3241          old_tail = root[0].tail
    3242
    3243          self.include( etree.ElementTree(root) )
    3244          self.assertEqual(old_text + content + old_tail,
    3245                            root.text)
    3246
    3247 -    def test_xinclude(self):
    3248          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'))
    3249          self.assertNotEqual(
    3250              'a',
    3251              tree.getroot()[1].tag)
    3252          # process xincludes
    3253          self.include( tree )
    3254          # check whether we find it replaced with included data
    3255          self.assertEqual(
    3256              'a',
    3257              tree.getroot()[1].tag)
    3258
    3259 -    def test_xinclude_resolver(self):
    3260          class res(etree.Resolver):
    3261              include_text = read_file(fileInTestDir('test.xml'))
    3262              called = {}
    3263              def resolve(self, url, id, context):
    3264                  if url.endswith(".dtd"):
    3265                      self.called["dtd"] = True
    3266                      return self.resolve_filename(
    3267                          fileInTestDir('test.dtd'), context)
    3268                  elif url.endswith("test_xinclude.xml"):
    3269                      self.called["input"] = True
    3270                      return None # delegate to default resolver
    3271                  else:
    3272                      self.called["include"] = True
    3273                      return self.resolve_string(self.include_text, context)
    3274
    3275          res_instance = res()
    3276          parser = etree.XMLParser(load_dtd = True)
    3277          parser.resolvers.add(res_instance)
    3278
    3279          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
    3280                             parser = parser)
    3281
    3282          self.include(tree)
    3283
    3284          called = list(res_instance.called.items())
    3285          called.sort()
    3286          self.assertEqual(
    3287              [("dtd", True), ("include", True), ("input", True)],
    3288              called)
    3289
    3290 -class ETreeXIncludeTestCase(_XIncludeTestCase):
    3291 -    def include(self, tree):
    3292          tree.xinclude()
    3293
    3294
    3295 -class ElementIncludeTestCase(_XIncludeTestCase):
    3296      from lxml import ElementInclude
    3297 -    def include(self, tree):
    3298          self.ElementInclude.include(tree.getroot())
    3299
    3300
    3301 -class ETreeC14NTestCase(HelperTestCase):
    3302 -    def test_c14n(self):
    3303          tree = self.parse(_bytes('<a><b/></a>'))
    3304          f = BytesIO()
    3305          tree.write_c14n(f)
    3306          s = f.getvalue()
    3307          self.assertEqual(_bytes('<a><b></b></a>'),
    3308                            s)
    3309
    3310 -    def test_c14n_gzip(self):
    3311          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    3312          f = BytesIO()
    3313          tree.write_c14n(f, compression=9)
    3314          gzfile = gzip.GzipFile(fileobj=BytesIO(f.getvalue()))
    3315          try:
    3316              s = gzfile.read()
    3317          finally:
    3318              gzfile.close()
    3319          self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'),
    3320                            s)
    3321
    3322 -    def test_c14n_file(self):
    3323          tree = self.parse(_bytes('<a><b/></a>'))
    3324          handle, filename = tempfile.mkstemp()
    3325          try:
    3326              tree.write_c14n(filename)
    3327              data = read_file(filename, 'rb')
    3328          finally:
    3329              os.close(handle)
    3330              os.remove(filename)
    3331          self.assertEqual(_bytes('<a><b></b></a>'),
    3332                            data)
    3333
    3334 -    def test_c14n_file_gzip(self):
    3335          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    3336          handle, filename = tempfile.mkstemp()
    3337          try:
    3338              tree.write_c14n(filename, compression=9)
    3339              f = gzip.open(filename, 'rb')
    3340              try:
    3341                  data = f.read()
    3342              finally:
    3343                  f.close()
    3344          finally:
    3345              os.close(handle)
    3346              os.remove(filename)
    3347          self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'),
    3348                            data)
    3349
    3350 -    def test_c14n_with_comments(self):
    3351          tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
    3352          f = BytesIO()
    3353          tree.write_c14n(f)
    3354          s = f.getvalue()
    3355          self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
    3356                            s)
    3357          f = BytesIO()
    3358          tree.write_c14n(f, with_comments=True)
    3359          s = f.getvalue()
    3360          self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
    3361                            s)
    3362          f = BytesIO()
    3363          tree.write_c14n(f, with_comments=False)
    3364          s = f.getvalue()
    3365          self.assertEqual(_bytes('<a><b></b></a>'),
    3366                            s)
    3367
    3368 -    def test_c14n_tostring_with_comments(self):
    3369          tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
    3370          s = etree.tostring(tree, method='c14n')
    3371          self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
    3372                            s)
    3373          s = etree.tostring(tree, method='c14n', with_comments=True)
    3374          self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
    3375                            s)
    3376          s = etree.tostring(tree, method='c14n', with_comments=False)
    3377          self.assertEqual(_bytes('<a><b></b></a>'),
    3378                            s)
    3379
    3380 -    def test_c14n_element_tostring_with_comments(self):
    3381          tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
    3382          s = etree.tostring(tree.getroot(), method='c14n')
    3383          self.assertEqual(_bytes('<a><!--ho--><b></b></a>'),
    3384                            s)
    3385          s = etree.tostring(tree.getroot(), method='c14n', with_comments=True)
    3386          self.assertEqual(_bytes('<a><!--ho--><b></b></a>'),
    3387                            s)
    3388          s = etree.tostring(tree.getroot(), method='c14n', with_comments=False)
    3389          self.assertEqual(_bytes('<a><b></b></a>'),
    3390                            s)
    3391
    3392 -    def test_c14n_exclusive(self):
    3393          tree = self.parse(_bytes(
    3394                  '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
    3395          f = BytesIO()
    3396          tree.write_c14n(f)
    3397          s = f.getvalue()
    3398          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    3399                            s)
    3400          f = BytesIO()
    3401          tree.write_c14n(f, exclusive=False)
    3402          s = f.getvalue()
    3403          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    3404                            s)
    3405          f = BytesIO()
    3406          tree.write_c14n(f, exclusive=True)
    3407          s = f.getvalue()
    3408          self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
    3409                            s)
    3410
    3411          f = BytesIO()
    3412          tree.write_c14n(f, exclusive=True, inclusive_ns_prefixes=['z'])
    3413          s = f.getvalue()
    3414          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:z="http://cde"><z:b></z:b></a>'),
    3415                            s)
    3416
    3417 -    def test_c14n_tostring_exclusive(self):
    3418          tree = self.parse(_bytes(
    3419                  '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
    3420          s = etree.tostring(tree, method='c14n')
    3421          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    3422                            s)
    3423          s = etree.tostring(tree, method='c14n', exclusive=False)
    3424          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    3425                            s)
    3426          s = etree.tostring(tree, method='c14n', exclusive=True)
    3427          self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
    3428                            s)
    3429
    3430          s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
    3431          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd"><z:b xmlns:z="http://cde"></z:b></a>'),
    3432                            s)
    3433
    3434 -    def test_c14n_element_tostring_exclusive(self):
    3435          tree = self.parse(_bytes(
    3436                  '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
    3437          s = etree.tostring(tree.getroot(), method='c14n')
    3438          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    3439                            s)
    3440          s = etree.tostring(tree.getroot(), method='c14n', exclusive=False)
    3441          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    3442                            s)
    3443          s = etree.tostring(tree.getroot(), method='c14n', exclusive=True)
    3444          self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
    3445                            s)
    3446
    3447          s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=False)
    3448          self.assertEqual(_bytes('<z:b xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
    3449                            s)
    3450          s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True)
    3451          self.assertEqual(_bytes('<z:b xmlns:z="http://cde"></z:b>'),
    3452                            s)
    3453
    3454          s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
    3455          self.assertEqual(_bytes('<z:b xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
    3456                            s)
    3457
    3458 -    def test_c14n_tostring_inclusive_ns_prefixes(self):
    3459          """ Regression test to fix memory allocation issues (use 3+ inclusive NS spaces)"""
    3460          tree = self.parse(_bytes(
    3461                  '<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
    3462
    3463          s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['x', 'y', 'z'])
    3464          self.assertEqual(_bytes('<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    3465                            s)
    3466
    3467
    3468 -class ETreeWriteTestCase(HelperTestCase):
    3469 -    def test_write(self):
    3470          tree = self.parse(_bytes('<a><b/></a>'))
    3471          f = BytesIO()
    3472          tree.write(f)
    3473          s = f.getvalue()
    3474          self.assertEqual(_bytes('<a><b/></a>'),
    3475                            s)
    3476
    3477 -    def test_write_gzip(self):
    3478          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    3479          f = BytesIO()
    3480          tree.write(f, compression=9)
    3481          gzfile = gzip.GzipFile(fileobj=BytesIO(f.getvalue()))
    3482          try:
    3483              s = gzfile.read()
    3484          finally:
    3485              gzfile.close()
    3486          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    3487                            s)
    3488
    3489 -    def test_write_gzip_level(self):
    3490          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    3491          f = BytesIO()
    3492          tree.write(f, compression=0)
    3493          s0 = f.getvalue()
    3494
    3495          f = BytesIO()
    3496          tree.write(f)
    3497          self.assertEqual(f.getvalue(), s0)
    3498
    3499          f = BytesIO()
    3500          tree.write(f, compression=1)
    3501          s = f.getvalue()
    3502          self.assertTrue(len(s) <= len(s0))
    3503          gzfile = gzip.GzipFile(fileobj=BytesIO(s))
    3504          try:
    3505              s1 = gzfile.read()
    3506          finally:
    3507              gzfile.close()
    3508
    3509          f = BytesIO()
    3510          tree.write(f, compression=9)
    3511          s = f.getvalue()
    3512          self.assertTrue(len(s) <= len(s0))
    3513          gzfile = gzip.GzipFile(fileobj=BytesIO(s))
    3514          try:
    3515              s9 = gzfile.read()
    3516          finally:
    3517              gzfile.close()
    3518
    3519          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    3520                            s0)
    3521          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    3522                            s1)
    3523          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    3524                            s9)
    3525
    3526 -    def test_write_file(self):
    3527          tree = self.parse(_bytes('<a><b/></a>'))
    3528          handle, filename = tempfile.mkstemp()
    3529          try:
    3530              tree.write(filename)
    3531              data = read_file(filename, 'rb')
    3532          finally:
    3533              os.close(handle)
    3534              os.remove(filename)
    3535          self.assertEqual(_bytes('<a><b/></a>'),
    3536                            data)
    3537
    3538 -    def test_write_file_gzip(self):
    3539          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    3540          handle, filename = tempfile.mkstemp()
    3541          try:
    3542              tree.write(filename, compression=9)
    3543              f = gzip.open(filename, 'rb')
    3544              try:
    3545                  data = f.read()
    3546              finally:
    3547                  f.close()
    3548          finally:
    3549              os.close(handle)
    3550              os.remove(filename)
    3551          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    3552                            data)
    3553
    3554 -    def test_write_file_gzip_parse(self):
    3555          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    3556          handle, filename = tempfile.mkstemp()
    3557          try:
    3558              tree.write(filename, compression=9)
    3559              data = etree.tostring(etree.parse(filename))
    3560          finally:
    3561              os.close(handle)
    3562              os.remove(filename)
    3563          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    3564                            data)
    3565
    3566 -    def test_write_file_gzipfile_parse(self):
    3567          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    3568          handle, filename = tempfile.mkstemp()
    3569          try:
    3570              tree.write(filename, compression=9)
    3571              data = etree.tostring(etree.parse(
    3572                  gzip.GzipFile(filename)))
    3573          finally:
    3574              os.close(handle)
    3575              os.remove(filename)
    3576          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    3577                            data)
    3578
    3579 -class ETreeErrorLogTest(HelperTestCase):
    3580      etree = etree
    3581
    3582 -    def test_parse_error_logging(self):
    3583          parse = self.etree.parse
    3584          f = BytesIO('<a><b></c></b></a>')
    3585          self.etree.clear_error_log()
    3586          try:
    3587              parse(f)
    3588              logs = None
    3589          except SyntaxError:
    3590              e = sys.exc_info()[1]
    3591              logs = e.error_log
    3592          f.close()
    3593          self.assertTrue([ log for log in logs
    3594                         if 'mismatch' in log.message ])
    3595          self.assertTrue([ log for log in logs
    3596                         if 'PARSER'   in log.domain_name])
    3597          self.assertTrue([ log for log in logs
    3598                         if 'ERR_TAG_NAME_MISMATCH' in log.type_name ])
    3599          self.assertTrue([ log for log in logs
    3600                         if 1 == log.line ])
    3601          self.assertTrue([ log for log in logs
    3602                         if 15 == log.column ])
    3603
    3604 -    def _test_python_error_logging(self):
    3605          """This can't really be tested as long as there isn't a way to
    3606          reset the logging setup ...
    3607          """
    3608          parse = self.etree.parse
    3609
    3610          messages = []
    3611          class Logger(self.etree.PyErrorLog):
    3612              def log(self, entry, message, *args):
    3613                  messages.append(message)
    3614
    3615          self.etree.use_global_python_log(Logger())
    3616          f = BytesIO('<a><b></c></b></a>')
    3617          try:
    3618              parse(f)
    3619          except SyntaxError:
    3620              pass
    3621          f.close()
    3622
    3623          self.assertTrue([ message for message in messages
    3624                         if 'mismatch' in message ])
    3625          self.assertTrue([ message for message in messages
    3626                         if ':PARSER:'   in message])
    3627          self.assertTrue([ message for message in messages
    3628                         if ':ERR_TAG_NAME_MISMATCH:' in message ])
    3629          self.assertTrue([ message for message in messages
    3630                         if ':1:15:' in message ])
    3631
    3632 -def test_suite():
    3633      suite = unittest.TestSuite()
    3634      suite.addTests([unittest.makeSuite(ETreeOnlyTestCase)])
    3635      suite.addTests([unittest.makeSuite(ETreeXIncludeTestCase)])
    3636      suite.addTests([unittest.makeSuite(ElementIncludeTestCase)])
    3637      suite.addTests([unittest.makeSuite(ETreeC14NTestCase)])
    3638      suite.addTests([unittest.makeSuite(ETreeWriteTestCase)])
    3639      suite.addTests([unittest.makeSuite(ETreeErrorLogTest)])
    3640      suite.addTests(
    3641          [make_doctest('../../../doc/tutorial.txt')])
    3642      if sys.version_info >= (2,5):
    3643          # now requires the 'with' statement
    3644          suite.addTests(
    3645              [make_doctest('../../../doc/api.txt')])
    3646      suite.addTests(
    3647          [make_doctest('../../../doc/FAQ.txt')])
    3648      suite.addTests(
    3649          [make_doctest('../../../doc/parsing.txt')])
    3650      suite.addTests(
    3651          [make_doctest('../../../doc/resolvers.txt')])
    3652      return suite
    3653
    3654  if __name__ == '__main__':
    3655      print('to test use test.py %s' % __file__)
    3656