lxml.tests.test_etree

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