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, unittest, copy, sys, operator
      11
      12  this_dir = os.path.dirname(__file__)
      13  if this_dir not in sys.path:
      14      sys.path.insert(0, this_dir) # needed for Py3
      15
      16  from common_imports import etree, StringIO, BytesIO, HelperTestCase, fileInTestDir
      17  from common_imports import LargeFileLikeUnicode, doctest, make_doctest
      18  from common_imports import canonicalize, sorted, _str, _bytes
      19
      20  print("")
      21  print("TESTED VERSION: %s" % etree.__version__)
      22  print("    Python:           " + repr(sys.version_info))
      23  print("    lxml.etree:       " + repr(etree.LXML_VERSION))
      24  print("    libxml used:      " + repr(etree.LIBXML_VERSION))
      25  print("    libxml compiled:  " + repr(etree.LIBXML_COMPILED_VERSION))
      26  print("    libxslt used:     " + repr(etree.LIBXSLT_VERSION))
      27  print("    libxslt compiled: " + repr(etree.LIBXSLT_COMPILED_VERSION))
      28  print("")
      29
      30  try:
      31      _unicode = unicode
      32  except NameError:
      33      # Python 3
      34      _unicode = str
      35
      36 -class ETreeOnlyTestCase(HelperTestCase):
      37      """Tests only for etree, not ElementTree"""
      38      etree = etree
      39
      40 -    def test_version(self):
      41          self.assert_(isinstance(etree.__version__, _unicode))
      42          self.assert_(isinstance(etree.LXML_VERSION, tuple))
      43          self.assertEqual(len(etree.LXML_VERSION), 4)
      44          self.assert_(isinstance(etree.LXML_VERSION[0], int))
      45          self.assert_(isinstance(etree.LXML_VERSION[1], int))
      46          self.assert_(isinstance(etree.LXML_VERSION[2], int))
      47          self.assert_(isinstance(etree.LXML_VERSION[3], int))
      48          self.assert_(etree.__version__.startswith(
      49              str(etree.LXML_VERSION[0])))
      50
      51 -    def test_c_api(self):
      52          if hasattr(self.etree, '__pyx_capi__'):
      53              # newer Pyrex compatible C-API
      54              self.assert_(isinstance(self.etree.__pyx_capi__, dict))
      55              self.assert_(len(self.etree.__pyx_capi__) > 0)
      56          else:
      57              # older C-API mechanism
      58              self.assert_(hasattr(self.etree, '_import_c_api'))
      59
      60 -    def test_element_names(self):
      61          Element = self.etree.Element
      62          el = Element('name')
      63          self.assertEquals(el.tag, 'name')
      64          el = Element('{}name')
      65          self.assertEquals(el.tag, 'name')
      66
      67 -    def test_element_name_empty(self):
      68          Element = self.etree.Element
      69          el = Element('name')
      70          self.assertRaises(ValueError, Element, '{}')
      71          self.assertRaises(ValueError, setattr, el, 'tag', '{}')
      72
      73          self.assertRaises(ValueError, Element, '{test}')
      74          self.assertRaises(ValueError, setattr, el, 'tag', '{test}')
      75
      76 -    def test_element_name_colon(self):
      77          Element = self.etree.Element
      78          self.assertRaises(ValueError, Element, 'p:name')
      79          self.assertRaises(ValueError, Element, '{test}p:name')
      80
      81          el = Element('name')
      82          self.assertRaises(ValueError, setattr, el, 'tag', 'p:name')
      83
      84 -    def test_element_name_quote(self):
      85          Element = self.etree.Element
      86          self.assertRaises(ValueError, Element, "p'name")
      87          self.assertRaises(ValueError, Element, 'p"name')
      88
      89          self.assertRaises(ValueError, Element, "{test}p'name")
      90          self.assertRaises(ValueError, Element, '{test}p"name')
      91
      92          el = Element('name')
      93          self.assertRaises(ValueError, setattr, el, 'tag', "p'name")
      94          self.assertRaises(ValueError, setattr, el, 'tag', 'p"name')
      95
      96 -    def test_element_name_space(self):
      97          Element = self.etree.Element
      98          self.assertRaises(ValueError, Element, ' name ')
      99          self.assertRaises(ValueError, Element, 'na me')
     100          self.assertRaises(ValueError, Element, '{test} name')
     101
     102          el = Element('name')
     103          self.assertRaises(ValueError, setattr, el, 'tag', ' name ')
     104
     105 -    def test_subelement_name_empty(self):
     106          Element = self.etree.Element
     107          SubElement = self.etree.SubElement
     108
     109          el = Element('name')
     110          self.assertRaises(ValueError, SubElement, el, '{}')
     111          self.assertRaises(ValueError, SubElement, el, '{test}')
     112
     113 -    def test_subelement_name_colon(self):
     114          Element = self.etree.Element
     115          SubElement = self.etree.SubElement
     116
     117          el = Element('name')
     118          self.assertRaises(ValueError, SubElement, el, 'p:name')
     119          self.assertRaises(ValueError, SubElement, el, '{test}p:name')
     120
     121 -    def test_subelement_name_quote(self):
     122          Element = self.etree.Element
     123          SubElement = self.etree.SubElement
     124
     125          el = Element('name')
     126          self.assertRaises(ValueError, SubElement, el, "p'name")
     127          self.assertRaises(ValueError, SubElement, el, "{test}p'name")
     128
     129          self.assertRaises(ValueError, SubElement, el, 'p"name')
     130          self.assertRaises(ValueError, SubElement, el, '{test}p"name')
     131
     132 -    def test_subelement_name_space(self):
     133          Element = self.etree.Element
     134          SubElement = self.etree.SubElement
     135
     136          el = Element('name')
     137          self.assertRaises(ValueError, SubElement, el, ' name ')
     138          self.assertRaises(ValueError, SubElement, el, 'na me')
     139          self.assertRaises(ValueError, SubElement, el, '{test} name')
     140
     141 -    def test_qname_empty(self):
     142          QName = self.etree.QName
     143          self.assertRaises(ValueError, QName, '')
     144          self.assertRaises(ValueError, QName, 'test', '')
     145
     146 -    def test_qname_colon(self):
     147          QName = self.etree.QName
     148          self.assertRaises(ValueError, QName, 'p:name')
     149          self.assertRaises(ValueError, QName, 'test', 'p:name')
     150
     151 -    def test_qname_space(self):
     152          QName = self.etree.QName
     153          self.assertRaises(ValueError, QName, ' name ')
     154          self.assertRaises(ValueError, QName, 'na me')
     155          self.assertRaises(ValueError, QName, 'test', ' name')
     156
     157 -    def test_qname_text_resolve(self):
     158          # ET doesn't resove QNames as text values
     159          etree = self.etree
     160          qname = etree.QName('http://myns', 'a')
     161          a = etree.Element(qname, nsmap={'p' : 'http://myns'})
     162          a.text = qname
     163
     164          self.assertEquals("p:a", a.text)
     165
     166 -    def test_nsmap_prefix_invalid(self):
     167          etree = self.etree
     168          self.assertRaises(ValueError,
     169                            etree.Element, "root", nsmap={'"' : 'testns'})
     170          self.assertRaises(ValueError,
     171                            etree.Element, "root", nsmap={'&' : 'testns'})
     172          self.assertRaises(ValueError,
     173                            etree.Element, "root", nsmap={'a:b' : 'testns'})
     174
     175 -    def test_attribute_set(self):
     176          Element = self.etree.Element
     177          root = Element("root")
     178          root.set("attr", "TEST")
     179          self.assertEquals("TEST", root.get("attr"))
     180
     181 -    def test_attribute_set_invalid(self):
     182          # ElementTree accepts arbitrary attribute values
     183          # lxml.etree allows only strings
     184          Element = self.etree.Element
     185          root = Element("root")
     186          self.assertRaises(TypeError, root.set, "newattr", 5)
     187          self.assertRaises(TypeError, root.set, "newattr", None)
     188
     189 -    def test_pi(self):
     190          # lxml.etree separates target and text
     191          Element = self.etree.Element
     192          SubElement = self.etree.SubElement
     193          ProcessingInstruction = self.etree.ProcessingInstruction
     194
     195          a = Element('a')
     196          a.append(ProcessingInstruction('foo', 'some more text'))
     197          self.assertEquals(a[0].target, 'foo')
     198          self.assertEquals(a[0].text, 'some more text')
     199
     200 -    def test_pi_parse(self):
     201          XML = self.etree.XML
     202          root = XML(_bytes("<test><?mypi my test ?></test>"))
     203          self.assertEquals(root[0].target, "mypi")
     204          self.assertEquals(root[0].text, "my test ")
     205
     206 -    def test_deepcopy_pi(self):
     207          # previously caused a crash
     208          ProcessingInstruction = self.etree.ProcessingInstruction
     209
     210          a = ProcessingInstruction("PI", "ONE")
     211          b = copy.deepcopy(a)
     212          b.text = "ANOTHER"
     213
     214          self.assertEquals('ONE',     a.text)
     215          self.assertEquals('ANOTHER', b.text)
     216
     217 -    def test_attribute_set(self):
     218          # ElementTree accepts arbitrary attribute values
     219          # lxml.etree allows only strings
     220          Element = self.etree.Element
     221
     222          root = Element("root")
     223          root.set("attr", "TEST")
     224          self.assertEquals("TEST", root.get("attr"))
     225          self.assertRaises(TypeError, root.set, "newattr", 5)
     226
     227 -    def test_parse_remove_comments(self):
     228          fromstring = self.etree.fromstring
     229          tostring = self.etree.tostring
     230          XMLParser = self.etree.XMLParser
     231
     232          xml = _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
     233          parser = XMLParser(remove_comments=True)
     234          root = fromstring(xml, parser)
     235          self.assertEquals(
     236              _bytes('<a><b><c/></b></a>'),
     237              tostring(root))
     238
     239 -    def test_parse_remove_pis(self):
     240          parse = self.etree.parse
     241          tostring = self.etree.tostring
     242          XMLParser = self.etree.XMLParser
     243
     244          xml = _bytes('<?test?><a><?A?><b><?B?><c/></b><?C?></a><?tail?>')
     245
     246          f = BytesIO(xml)
     247          tree = parse(f)
     248          self.assertEquals(
     249              xml,
     250              tostring(tree))
     251
     252          parser = XMLParser(remove_pis=True)
     253          tree = parse(f, parser)
     254          self.assertEquals(
     255              _bytes('<a><b><c/></b></a>'),
     256              tostring(tree))
     257
     258 -    def test_parse_parser_type_error(self):
     259          # ET raises IOError only
     260          parse = self.etree.parse
     261          self.assertRaises(TypeError, parse, 'notthere.xml', object())
     262
     263 -    def test_parse_error_logging(self):
     264          parse = self.etree.parse
     265          f = BytesIO('<a><b></c></b></a>')
     266          self.etree.clear_error_log()
     267          try:
     268              parse(f)
     269              logs = None
     270          except SyntaxError:
     271              e = sys.exc_info()[1]
     272              logs = e.error_log
     273          f.close()
     274          self.assert_([ log for log in logs
     275                         if 'mismatch' in log.message ])
     276          self.assert_([ log for log in logs
     277                         if 'PARSER'   in log.domain_name])
     278          self.assert_([ log for log in logs
     279                         if 'TAG_NAME_MISMATCH' in log.type_name ])
     280          self.assert_([ log for log in logs
     281                         if 1 == log.line ])
     282          self.assert_([ log for log in logs
     283                         if 15 == log.column ])
     284
     285 -    def test_iterparse_tree_comments(self):
     286          # ET removes comments
     287          iterparse = self.etree.iterparse
     288          tostring = self.etree.tostring
     289
     290          f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
     291          events = list(iterparse(f))
     292          root = events[-1][1]
     293          self.assertEquals(3, len(events))
     294          self.assertEquals(
     295              _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
     296              tostring(root))
     297
     298 -    def test_iterparse_comments(self):
     299          # ET removes comments
     300          iterparse = self.etree.iterparse
     301          tostring = self.etree.tostring
     302
     303          def name(event, el):
     304              if event == 'comment':
     305                  return el.text
     306              else:
     307                  return el.tag
     308
     309          f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
     310          events = list(iterparse(f, events=('end', 'comment')))
     311          root = events[-1][1]
     312          self.assertEquals(6, len(events))
     313          self.assertEquals(['A', ' B ', 'c', 'b', 'C', 'a'],
     314                            [ name(*item) for item in events ])
     315          self.assertEquals(
     316              _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
     317              tostring(root))
     318
     319 -    def test_iterparse_pis(self):
     320          # ET removes pis
     321          iterparse = self.etree.iterparse
     322          tostring = self.etree.tostring
     323          ElementTree = self.etree.ElementTree
     324
     325          def name(event, el):
     326              if event == 'pi':
     327                  return (el.target, el.text)
     328              else:
     329                  return el.tag
     330
     331          f = BytesIO('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>')
     332          events = list(iterparse(f, events=('end', 'pi')))
     333          root = events[-2][1]
     334          self.assertEquals(8, len(events))
     335          self.assertEquals([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b',
     336                             ('pid','d'), 'a', ('pie','e')],
     337                            [ name(*item) for item in events ])
     338          self.assertEquals(
     339              _bytes('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>'),
     340              tostring(ElementTree(root)))
     341
     342 -    def test_iterparse_remove_comments(self):
     343          iterparse = self.etree.iterparse
     344          tostring = self.etree.tostring
     345
     346          f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
     347          events = list(iterparse(f, remove_comments=True,
     348                                  events=('end', 'comment')))
     349          root = events[-1][1]
     350          self.assertEquals(3, len(events))
     351          self.assertEquals(['c', 'b', 'a'],
     352                            [ el.tag for (event, el) in events ])
     353          self.assertEquals(
     354              _bytes('<a><b><c/></b></a>'),
     355              tostring(root))
     356
     357 -    def test_iterparse_broken(self):
     358          iterparse = self.etree.iterparse
     359          f = BytesIO('<a><b><c/></a>')
     360          # ET raises ExpatError, lxml raises XMLSyntaxError
     361          self.assertRaises(self.etree.XMLSyntaxError, list, iterparse(f))
     362
     363 -    def test_iterparse_strip(self):
     364          iterparse = self.etree.iterparse
     365          f = BytesIO("""
     366                 <a>  \n \n  <b> b test </b>  \n
     367
     368                 \n\t <c> \n </c> </a>  \n """)
     369          iterator = iterparse(f, remove_blank_text=True)
     370          text = [ (element.text, element.tail)
     371                   for event, element in iterator ]
     372          self.assertEquals(
     373              [(" b test ", None), (" \n ", None), (None, None)],
     374              text)
     375
     376 -    def test_iterparse_tag(self):
     377          iterparse = self.etree.iterparse
     378          f = BytesIO('<a><b><d/></b><c/></a>')
     379
     380          iterator = iterparse(f, tag="b", events=('start', 'end'))
     381          events = list(iterator)
     382          root = iterator.root
     383          self.assertEquals(
     384              [('start', root[0]), ('end', root[0])],
     385              events)
     386
     387 -    def test_iterparse_tag_all(self):
     388          iterparse = self.etree.iterparse
     389          f = BytesIO('<a><b><d/></b><c/></a>')
     390
     391          iterator = iterparse(f, tag="*", events=('start', 'end'))
     392          events = list(iterator)
     393          self.assertEquals(
     394              8,
     395              len(events))
     396
     397 -    def test_iterparse_encoding_error(self):
     398          text = _str('Søk på nettet')
     399          wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
     400          xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
     401                        ).encode('iso-8859-1')
     402
     403          self.assertRaises(self.etree.ParseError,
     404                            list, self.etree.iterparse(BytesIO(xml_latin1)))
     405
     406 -    def test_iterparse_encoding_8bit_override(self):
     407          text = _str('Søk på nettet', encoding="UTF-8")
     408          wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
     409          xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
     410                        ).encode('iso-8859-1')
     411
     412          iterator = self.etree.iterparse(BytesIO(xml_latin1),
     413                                          encoding="iso-8859-1")
     414          self.assertEquals(1, len(list(iterator)))
     415
     416          a = iterator.root
     417          self.assertEquals(a.text, text)
     418
     419 -    def test_iterparse_keep_cdata(self):
     420          tostring = self.etree.tostring
     421          f = BytesIO('<root><![CDATA[test]]></root>')
     422          context = self.etree.iterparse(f, strip_cdata=False)
     423          content = [ el.text for event,el in context ]
     424
     425          self.assertEquals(['test'], content)
     426          self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
     427                            tostring(context.root))
     428
     429 -    def test_parser_encoding_unknown(self):
     430          self.assertRaises(
     431              LookupError, self.etree.XMLParser, encoding="hopefully unknown")
     432
     433 -    def test_elementtree_parser_target_type_error(self):
     434          assertEquals = self.assertEquals
     435          assertFalse  = self.assertFalse
     436
     437          events = []
     438          class Target(object):
     439              def start(self, tag, attrib):
     440                  events.append("start")
     441                  assertFalse(attrib)
     442                  assertEquals("TAG", tag)
     443              def end(self, tag):
     444                  events.append("end")
     445                  assertEquals("TAG", tag)
     446              def close(self):
     447                  return "DONE" # no Element!
     448
     449          parser = self.etree.XMLParser(target=Target())
     450          tree = self.etree.ElementTree()
     451
     452          self.assertRaises(TypeError,
     453                            tree.parse, BytesIO("<TAG/>"), parser=parser)
     454          self.assertEquals(["start", "end"], events)
     455
     456 -    def test_parser_target_comment(self):
     457          events = []
     458          class Target(object):
     459              def start(self, tag, attrib):
     460                  events.append("start-" + tag)
     461              def end(self, tag):
     462                  events.append("end-" + tag)
     463              def data(self, data):
     464                  events.append("data-" + data)
     465              def comment(self, text):
     466                  events.append("comment-" + text)
     467              def close(self):
     468                  return "DONE"
     469
     470          parser = self.etree.XMLParser(target=Target())
     471
     472          parser.feed(_bytes('<!--a--><root>A<!--b--><sub/><!--c-->B</root><!--d-->'))
     473          done = parser.close()
     474
     475          self.assertEquals("DONE", done)
     476          self.assertEquals(["comment-a", "start-root", "data-A", "comment-b",
     477                             "start-sub", "end-sub", "comment-c", "data-B",
     478                             "end-root", "comment-d"],
     479                            events)
     480
     481 -    def test_parser_target_pi(self):
     482          events = []
     483          class Target(object):
     484              def start(self, tag, attrib):
     485                  events.append("start-" + tag)
     486              def end(self, tag):
     487                  events.append("end-" + tag)
     488              def data(self, data):
     489                  events.append("data-" + data)
     490              def pi(self, target, data):
     491                  events.append("pi-" + target + "-" + data)
     492              def close(self):
     493                  return "DONE"
     494
     495          parser = self.etree.XMLParser(target=Target())
     496
     497          parser.feed(_bytes('<?test a?><root>A<?test b?>B</root><?test c?>'))
     498          done = parser.close()
     499
     500          self.assertEquals("DONE", done)
     501          self.assertEquals(["pi-test-a", "start-root", "data-A", "pi-test-b",
     502                             "data-B", "end-root", "pi-test-c"],
     503                            events)
     504
     505 -    def test_parser_target_cdata(self):
     506          events = []
     507          class Target(object):
     508              def start(self, tag, attrib):
     509                  events.append("start-" + tag)
     510              def end(self, tag):
     511                  events.append("end-" + tag)
     512              def data(self, data):
     513                  events.append("data-" + data)
     514              def close(self):
     515                  return "DONE"
     516
     517          parser = self.etree.XMLParser(target=Target(),
     518                                        strip_cdata=False)
     519
     520          parser.feed(_bytes('<root>A<a><![CDATA[ca]]></a>B</root>'))
     521          done = parser.close()
     522
     523          self.assertEquals("DONE", done)
     524          self.assertEquals(["start-root", "data-A", "start-a",
     525                             "data-ca", "end-a", "data-B", "end-root"],
     526                            events)
     527
     528 -    def test_parser_target_recover(self):
     529          events = []
     530          class Target(object):
     531              def start(self, tag, attrib):
     532                  events.append("start-" + tag)
     533              def end(self, tag):
     534                  events.append("end-" + tag)
     535              def data(self, data):
     536                  events.append("data-" + data)
     537              def close(self):
     538                  events.append("close")
     539                  return "DONE"
     540
     541          parser = self.etree.XMLParser(target=Target(),
     542                                        recover=True)
     543
     544          parser.feed(_bytes('<root>A<a>ca</a>B</not-root>'))
     545          done = parser.close()
     546
     547          self.assertEquals("DONE", done)
     548          self.assertEquals(["start-root", "data-A", "start-a",
     549                             "data-ca", "end-a", "data-B",
     550                             "end-root", "close"],
     551                            events)
     552
     553 -    def test_iterwalk_tag(self):
     554          iterwalk = self.etree.iterwalk
     555          root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
     556
     557          iterator = iterwalk(root, tag="b", events=('start', 'end'))
     558          events = list(iterator)
     559          self.assertEquals(
     560              [('start', root[0]), ('end', root[0])],
     561              events)
     562
     563 -    def test_iterwalk_tag_all(self):
     564          iterwalk = self.etree.iterwalk
     565          root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
     566
     567          iterator = iterwalk(root, tag="*", events=('start', 'end'))
     568          events = list(iterator)
     569          self.assertEquals(
     570              8,
     571              len(events))
     572
     573 -    def test_iterwalk(self):
     574          iterwalk = self.etree.iterwalk
     575          root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
     576
     577          events = list(iterwalk(root))
     578          self.assertEquals(
     579              [('end', root[0]), ('end', root[1]), ('end', root)],
     580              events)
     581
     582 -    def test_iterwalk_start(self):
     583          iterwalk = self.etree.iterwalk
     584          root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
     585
     586          iterator = iterwalk(root, events=('start',))
     587          events = list(iterator)
     588          self.assertEquals(
     589              [('start', root), ('start', root[0]), ('start', root[1])],
     590              events)
     591
     592 -    def test_iterwalk_start_end(self):
     593          iterwalk = self.etree.iterwalk
     594          root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
     595
     596          iterator = iterwalk(root, events=('start','end'))
     597          events = list(iterator)
     598          self.assertEquals(
     599              [('start', root), ('start', root[0]), ('end', root[0]),
     600               ('start', root[1]), ('end', root[1]), ('end', root)],
     601              events)
     602
     603 -    def test_iterwalk_clear(self):
     604          iterwalk = self.etree.iterwalk
     605          root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
     606
     607          iterator = iterwalk(root)
     608          for event, elem in iterator:
     609              elem.clear()
     610
     611          self.assertEquals(0,
     612                            len(root))
     613
     614 -    def test_iterwalk_attrib_ns(self):
     615          iterwalk = self.etree.iterwalk
     616          root = self.etree.XML(_bytes('<a xmlns="ns1"><b><c xmlns="ns2"/></b></a>'))
     617
     618          attr_name = '{testns}bla'
     619          events = []
     620          iterator = iterwalk(root, events=('start','end','start-ns','end-ns'))
     621          for event, elem in iterator:
     622              events.append(event)
     623              if event == 'start':
     624                  if elem.tag != '{ns1}a':
     625                      elem.set(attr_name, 'value')
     626
     627          self.assertEquals(
     628              ['start-ns', 'start', 'start', 'start-ns', 'start',
     629               'end', 'end-ns', 'end', 'end', 'end-ns'],
     630              events)
     631
     632          self.assertEquals(
     633              None,
     634              root.get(attr_name))
     635          self.assertEquals(
     636              'value',
     637              root[0].get(attr_name))
     638
     639 -    def test_iterwalk_getiterator(self):
     640          iterwalk = self.etree.iterwalk
     641          root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
     642
     643          counts = []
     644          for event, elem in iterwalk(root):
     645              counts.append(len(list(elem.getiterator())))
     646          self.assertEquals(
     647              [1,2,1,4],
     648              counts)
     649
     650 -    def test_resolve_string_dtd(self):
     651          parse = self.etree.parse
     652          parser = self.etree.XMLParser(dtd_validation=True)
     653          assertEqual = self.assertEqual
     654          test_url = _str("__nosuch.dtd")
     655
     656          class MyResolver(self.etree.Resolver):
     657              def resolve(self, url, id, context):
     658                  assertEqual(url, test_url)
     659                  return self.resolve_string(
     660                      _str('''<!ENTITY myentity "%s">
     661                          <!ELEMENT doc ANY>''') % url, context)
     662
     663          parser.resolvers.add(MyResolver())
     664
     665          xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
     666          tree = parse(StringIO(xml), parser)
     667          root = tree.getroot()
     668          self.assertEquals(root.text, test_url)
     669
     670 -    def test_resolve_filename_dtd(self):
     671          parse = self.etree.parse
     672          parser = self.etree.XMLParser(attribute_defaults=True)
     673          assertEqual = self.assertEqual
     674          test_url = _str("__nosuch.dtd")
     675
     676          class MyResolver(self.etree.Resolver):
     677              def resolve(self, url, id, context):
     678                  assertEqual(url, test_url)
     679                  return self.resolve_filename(
     680                      fileInTestDir('test.dtd'), context)
     681
     682          parser.resolvers.add(MyResolver())
     683
     684          xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
     685          tree = parse(StringIO(xml), parser)
     686          root = tree.getroot()
     687          self.assertEquals(
     688              root.attrib,    {'default': 'valueA'})
     689          self.assertEquals(
     690              root[0].attrib, {'default': 'valueB'})
     691
     692 -    def test_resolve_filename_dtd_relative(self):
     693          parse = self.etree.parse
     694          parser = self.etree.XMLParser(attribute_defaults=True)
     695          assertEqual = self.assertEqual
     696          test_url = _str("__nosuch.dtd")
     697
     698          class MyResolver(self.etree.Resolver):
     699              def resolve(self, url, id, context):
     700                  assertEqual(url, fileInTestDir(test_url))
     701                  return self.resolve_filename(
     702                      fileInTestDir('test.dtd'), context)
     703
     704          parser.resolvers.add(MyResolver())
     705
     706          xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
     707          tree = parse(StringIO(xml), parser,
     708                       base_url=fileInTestDir('__test.xml'))
     709          root = tree.getroot()
     710          self.assertEquals(
     711              root.attrib,    {'default': 'valueA'})
     712          self.assertEquals(
     713              root[0].attrib, {'default': 'valueB'})
     714
     715 -    def test_resolve_empty(self):
     716          parse = self.etree.parse
     717          parser = self.etree.XMLParser(load_dtd=True)
     718          assertEqual = self.assertEqual
     719          test_url = _str("__nosuch.dtd")
     720
     721          class check(object):
     722              resolved = False
     723
     724          class MyResolver(self.etree.Resolver):
     725              def resolve(self, url, id, context):
     726                  assertEqual(url, test_url)
     727                  check.resolved = True
     728                  return self.resolve_empty(context)
     729
     730          parser.resolvers.add(MyResolver())
     731
     732          xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
     733          self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser)
     734          self.assert_(check.resolved)
     735
     736 -    def test_resolve_error(self):
     737          parse = self.etree.parse
     738          parser = self.etree.XMLParser(dtd_validation=True)
     739
     740          class _LocalException(Exception):
     741              pass
     742
     743          class MyResolver(self.etree.Resolver):
     744              def resolve(self, url, id, context):
     745                  raise _LocalException
     746
     747          parser.resolvers.add(MyResolver())
     748
     749          xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>'
     750          self.assertRaises(_LocalException, parse, BytesIO(xml), parser)
     751
     752      if etree.LIBXML_VERSION > (2,6,20):
     753 -        def test_entity_parse(self):
     754              parse = self.etree.parse
     755              tostring = self.etree.tostring
     756              parser = self.etree.XMLParser(resolve_entities=False)
     757              Entity = self.etree.Entity
     758
     759              xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>'
     760              tree = parse(BytesIO(xml), parser)
     761              root = tree.getroot()
     762              self.assertEquals(root[0].tag, Entity)
     763              self.assertEquals(root[0].text, "&myentity;")
     764              self.assertEquals(root[0].tail, None)
     765              self.assertEquals(root[0].name, "myentity")
     766
     767              self.assertEquals(_bytes('<doc>&myentity;</doc>'),
     768                                tostring(root))
     769
     770 -    def test_entity_append(self):
     771          Entity = self.etree.Entity
     772          Element = self.etree.Element
     773          tostring = self.etree.tostring
     774
     775          root = Element("root")
     776          root.append( Entity("test") )
     777
     778          self.assertEquals(root[0].tag, Entity)
     779          self.assertEquals(root[0].text, "&test;")
     780          self.assertEquals(root[0].tail, None)
     781          self.assertEquals(root[0].name, "test")
     782
     783          self.assertEquals(_bytes('<root>&test;</root>'),
     784                            tostring(root))
     785
     786 -    def test_entity_values(self):
     787          Entity = self.etree.Entity
     788          self.assertEquals(Entity("test").text, '&test;')
     789          self.assertEquals(Entity("#17683").text, '&#17683;')
     790          self.assertEquals(Entity("#x1768").text, '&#x1768;')
     791          self.assertEquals(Entity("#x98AF").text, '&#x98AF;')
     792
     793 -    def test_entity_error(self):
     794          Entity = self.etree.Entity
     795          self.assertRaises(ValueError, Entity, 'a b c')
     796          self.assertRaises(ValueError, Entity, 'a,b')
     797          self.assertRaises(ValueError, Entity, 'a\0b')
     798          self.assertRaises(ValueError, Entity, '#abc')
     799          self.assertRaises(ValueError, Entity, '#xxyz')
     800
     801 -    def test_cdata(self):
     802          CDATA = self.etree.CDATA
     803          Element = self.etree.Element
     804          tostring = self.etree.tostring
     805
     806          root = Element("root")
     807          root.text = CDATA('test')
     808
     809          self.assertEquals('test',
     810                            root.text)
     811          self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
     812                            tostring(root))
     813
     814 -    def test_cdata_type(self):
     815          CDATA = self.etree.CDATA
     816          Element = self.etree.Element
     817          root = Element("root")
     818
     819          root.text = CDATA("test")
     820          self.assertEquals('test', root.text)
     821
     822          root.text = CDATA(_str("test"))
     823          self.assertEquals('test', root.text)
     824
     825          self.assertRaises(TypeError, CDATA, 1)
     826
     827 -    def test_cdata_errors(self):
     828          CDATA = self.etree.CDATA
     829          Element = self.etree.Element
     830
     831          root = Element("root")
     832          cdata = CDATA('test')
     833
     834          self.assertRaises(TypeError,
     835                            setattr, root, 'tail', cdata)
     836          self.assertRaises(TypeError,
     837                            root.set, 'attr', cdata)
     838          self.assertRaises(TypeError,
     839                            operator.setitem, root.attrib, 'attr', cdata)
     840
     841 -    def test_cdata_parser(self):
     842          tostring = self.etree.tostring
     843          parser = self.etree.XMLParser(strip_cdata=False)
     844          root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
     845
     846          self.assertEquals('test', root.text)
     847          self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
     848                            tostring(root))
     849
     850      # TypeError in etree, AssertionError in ElementTree;
     851 -    def test_setitem_assert(self):
     852          Element = self.etree.Element
     853          SubElement = self.etree.SubElement
     854
     855          a = Element('a')
     856          b = SubElement(a, 'b')
     857
     858          self.assertRaises(TypeError,
     859                            a.__setitem__, 0, 'foo')
     860
     861 -    def test_append_None(self):
     862          # raises AssertionError in ElementTree
     863          Element = self.etree.Element
     864          self.assertRaises(TypeError, Element('a').append, None)
     865
     866 -    def test_addnext(self):
     867          Element = self.etree.Element
     868          SubElement = self.etree.SubElement
     869          root = Element('root')
     870          SubElement(root, 'a')
     871          SubElement(root, 'b')
     872
     873          self.assertEquals(['a', 'b'],
     874                            [c.tag for c in root])
     875          root[1].addnext(root[0])
     876          self.assertEquals(['b', 'a'],
     877                            [c.tag for c in root])
     878
     879 -    def test_addprevious(self):
     880          Element = self.etree.Element
     881          SubElement = self.etree.SubElement
     882          root = Element('root')
     883          SubElement(root, 'a')
     884          SubElement(root, 'b')
     885
     886          self.assertEquals(['a', 'b'],
     887                            [c.tag for c in root])
     888          root[0].addprevious(root[1])
     889          self.assertEquals(['b', 'a'],
     890                            [c.tag for c in root])
     891
     892 -    def test_addnext_root(self):
     893          Element = self.etree.Element
     894          a = Element('a')
     895          b = Element('b')
     896          self.assertRaises(TypeError, a.addnext, b)
     897
     898 -    def test_addnext_root(self):
     899          Element = self.etree.Element
     900          a = Element('a')
     901          b = Element('b')
     902          self.assertRaises(TypeError, a.addnext, b)
     903
     904 -    def test_addprevious_pi(self):
     905          Element = self.etree.Element
     906          SubElement = self.etree.SubElement
     907          PI = self.etree.PI
     908          root = Element('root')
     909          SubElement(root, 'a')
     910          pi = PI('TARGET', 'TEXT')
     911          pi.tail = "TAIL"
     912
     913          self.assertEquals(_bytes('<root><a></a></root>'),
     914                            self._writeElement(root))
     915          root[0].addprevious(pi)
     916          self.assertEquals(_bytes('<root><?TARGET TEXT?>TAIL<a></a></root>'),
     917                            self._writeElement(root))
     918
     919 -    def test_addprevious_root_pi(self):
     920          Element = self.etree.Element
     921          PI = self.etree.PI
     922          root = Element('root')
     923          pi = PI('TARGET', 'TEXT')
     924          pi.tail = "TAIL"
     925
     926          self.assertEquals(_bytes('<root></root>'),
     927                            self._writeElement(root))
     928          root.addprevious(pi)
     929          self.assertEquals(_bytes('<?TARGET TEXT?>\n<root></root>'),
     930                            self._writeElement(root))
     931
     932 -    def test_addnext_pi(self):
     933          Element = self.etree.Element
     934          SubElement = self.etree.SubElement
     935          PI = self.etree.PI
     936          root = Element('root')
     937          SubElement(root, 'a')
     938          pi = PI('TARGET', 'TEXT')
     939          pi.tail = "TAIL"
     940
     941          self.assertEquals(_bytes('<root><a></a></root>'),
     942                            self._writeElement(root))
     943          root[0].addnext(pi)
     944          self.assertEquals(_bytes('<root><a></a><?TARGET TEXT?>TAIL</root>'),
     945                            self._writeElement(root))
     946
     947 -    def test_addnext_root_pi(self):
     948          Element = self.etree.Element
     949          PI = self.etree.PI
     950          root = Element('root')
     951          pi = PI('TARGET', 'TEXT')
     952          pi.tail = "TAIL"
     953
     954          self.assertEquals(_bytes('<root></root>'),
     955                            self._writeElement(root))
     956          root.addnext(pi)
     957          self.assertEquals(_bytes('<root></root>\n<?TARGET TEXT?>'),
     958                            self._writeElement(root))
     959
     960 -    def test_addnext_comment(self):
     961          Element = self.etree.Element
     962          SubElement = self.etree.SubElement
     963          Comment = self.etree.Comment
     964          root = Element('root')
     965          SubElement(root, 'a')
     966          comment = Comment('TEXT ')
     967          comment.tail = "TAIL"
     968
     969          self.assertEquals(_bytes('<root><a></a></root>'),
     970                            self._writeElement(root))
     971          root[0].addnext(comment)
     972          self.assertEquals(_bytes('<root><a></a><!--TEXT -->TAIL</root>'),
     973                            self._writeElement(root))
     974
     975 -    def test_addnext_root_comment(self):
     976          Element = self.etree.Element
     977          Comment = self.etree.Comment
     978          root = Element('root')
     979          comment = Comment('TEXT ')
     980          comment.tail = "TAIL"
     981
     982          self.assertEquals(_bytes('<root></root>'),
     983                            self._writeElement(root))
     984          root.addnext(comment)
     985          self.assertEquals(_bytes('<root></root>\n<!--TEXT -->'),
     986                            self._writeElement(root))
     987
     988 -    def test_addprevious_comment(self):
     989          Element = self.etree.Element
     990          SubElement = self.etree.SubElement
     991          Comment = self.etree.Comment
     992          root = Element('root')
     993          SubElement(root, 'a')
     994          comment = Comment('TEXT ')
     995          comment.tail = "TAIL"
     996
     997          self.assertEquals(_bytes('<root><a></a></root>'),
     998                            self._writeElement(root))
     999          root[0].addprevious(comment)
    1000          self.assertEquals(_bytes('<root><!--TEXT -->TAIL<a></a></root>'),
    1001                            self._writeElement(root))
    1002
    1003 -    def test_addprevious_root_comment(self):
    1004          Element = self.etree.Element
    1005          Comment = self.etree.Comment
    1006          root = Element('root')
    1007          comment = Comment('TEXT ')
    1008          comment.tail = "TAIL"
    1009
    1010          self.assertEquals(_bytes('<root></root>'),
    1011                            self._writeElement(root))
    1012          root.addprevious(comment)
    1013          self.assertEquals(_bytes('<!--TEXT -->\n<root></root>'),
    1014                            self._writeElement(root))
    1015
    1016      # ET's Elements have items() and key(), but not values()
    1017 -    def test_attribute_values(self):
    1018          XML = self.etree.XML
    1019
    1020          root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
    1021          values = root.values()
    1022          values.sort()
    1023          self.assertEquals(['Alpha', 'Beta', 'Gamma'], values)
    1024
    1025      # gives error in ElementTree
    1026 -    def test_comment_empty(self):
    1027          Element = self.etree.Element
    1028          Comment = self.etree.Comment
    1029
    1030          a = Element('a')
    1031          a.append(Comment())
    1032          self.assertEquals(
    1033              _bytes('<a><!----></a>'),
    1034              self._writeElement(a))
    1035
    1036      # ElementTree ignores comments
    1037 -    def test_comment_parse_empty(self):
    1038          ElementTree = self.etree.ElementTree
    1039          tostring = self.etree.tostring
    1040
    1041          xml = _bytes('<a><b/><!----><c/></a>')
    1042          f = BytesIO(xml)
    1043          doc = ElementTree(file=f)
    1044          a = doc.getroot()
    1045          self.assertEquals(
    1046              '',
    1047              a[1].text)
    1048          self.assertEquals(
    1049              xml,
    1050              tostring(a))
    1051
    1052      # ElementTree ignores comments
    1053 -    def test_comment_no_proxy_yet(self):
    1054          ElementTree = self.etree.ElementTree
    1055
    1056          f = BytesIO('<a><b></b><!-- hoi --><c></c></a>')
    1057          doc = ElementTree(file=f)
    1058          a = doc.getroot()
    1059          self.assertEquals(
    1060              ' hoi ',
    1061              a[1].text)
    1062
    1063      # does not raise an exception in ElementTree
    1064 -    def test_comment_immutable(self):
    1065          Element = self.etree.Element
    1066          Comment = self.etree.Comment
    1067
    1068          c = Comment()
    1069          el = Element('myel')
    1070
    1071          self.assertRaises(TypeError, c.append, el)
    1072          self.assertRaises(TypeError, c.insert, 0, el)
    1073          self.assertRaises(TypeError, c.set, "myattr", "test")
    1074
    1075      # test passing 'None' to dump
    1076 -    def test_dump_none(self):
    1077          self.assertRaises(TypeError, self.etree.dump, None)
    1078
    1079 -    def test_prefix(self):
    1080          ElementTree = self.etree.ElementTree
    1081
    1082          f = BytesIO('<a xmlns:foo="http://www.infrae.com/ns/1"><foo:b/></a>')
    1083          doc = ElementTree(file=f)
    1084          a = doc.getroot()
    1085          self.assertEquals(
    1086              None,
    1087              a.prefix)
    1088          self.assertEquals(
    1089              'foo',
    1090              a[0].prefix)
    1091
    1092 -    def test_prefix_default_ns(self):
    1093          ElementTree = self.etree.ElementTree
    1094
    1095          f = BytesIO('<a xmlns="http://www.infrae.com/ns/1"><b/></a>')
    1096          doc = ElementTree(file=f)
    1097          a = doc.getroot()
    1098          self.assertEquals(
    1099              None,
    1100              a.prefix)
    1101          self.assertEquals(
    1102              None,
    1103              a[0].prefix)
    1104
    1105 -    def test_getparent(self):
    1106          Element = self.etree.Element
    1107          SubElement = self.etree.SubElement
    1108
    1109          a = Element('a')
    1110          b = SubElement(a, 'b')
    1111          c = SubElement(a, 'c')
    1112          d = SubElement(b, 'd')
    1113          self.assertEquals(
    1114              None,
    1115              a.getparent())
    1116          self.assertEquals(
    1117              a,
    1118              b.getparent())
    1119          self.assertEquals(
    1120              b.getparent(),
    1121              c.getparent())
    1122          self.assertEquals(
    1123              b,
    1124              d.getparent())
    1125
    1126 -    def test_iterchildren(self):
    1127          XML = self.etree.XML
    1128
    1129          root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
    1130          result = []
    1131          for el in root.iterchildren():
    1132              result.append(el.tag)
    1133          self.assertEquals(['one', 'two', 'three'], result)
    1134
    1135 -    def test_iterchildren_reversed(self):
    1136          XML = self.etree.XML
    1137
    1138          root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
    1139          result = []
    1140          for el in root.iterchildren(reversed=True):
    1141              result.append(el.tag)
    1142          self.assertEquals(['three', 'two', 'one'], result)
    1143
    1144 -    def test_iterchildren_tag(self):
    1145          XML = self.etree.XML
    1146
    1147          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
    1148          result = []
    1149          for el in root.iterchildren(tag='two'):
    1150              result.append(el.text)
    1151          self.assertEquals(['Two', 'Bla'], result)
    1152
    1153 -    def test_iterchildren_tag_reversed(self):
    1154          XML = self.etree.XML
    1155
    1156          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
    1157          result = []
    1158          for el in root.iterchildren(reversed=True, tag='two'):
    1159              result.append(el.text)
    1160          self.assertEquals(['Bla', 'Two'], result)
    1161
    1162 -    def test_iterancestors(self):
    1163          Element    = self.etree.Element
    1164          SubElement = self.etree.SubElement
    1165
    1166          a = Element('a')
    1167          b = SubElement(a, 'b')
    1168          c = SubElement(a, 'c')
    1169          d = SubElement(b, 'd')
    1170          self.assertEquals(
    1171              [],
    1172              list(a.iterancestors()))
    1173          self.assertEquals(
    1174              [a],
    1175              list(b.iterancestors()))
    1176          self.assertEquals(
    1177              [a],
    1178              list(c.iterancestors()))
    1179          self.assertEquals(
    1180              [b, a],
    1181              list(d.iterancestors()))
    1182
    1183 -    def test_iterancestors_tag(self):
    1184          Element    = self.etree.Element
    1185          SubElement = self.etree.SubElement
    1186
    1187          a = Element('a')
    1188          b = SubElement(a, 'b')
    1189          c = SubElement(a, 'c')
    1190          d = SubElement(b, 'd')
    1191          self.assertEquals(
    1192              [a],
    1193              list(d.iterancestors(tag='a')))
    1194
    1195 -    def test_iterdescendants(self):
    1196          Element = self.etree.Element
    1197          SubElement = self.etree.SubElement
    1198
    1199          a = Element('a')
    1200          b = SubElement(a, 'b')
    1201          c = SubElement(a, 'c')
    1202          d = SubElement(b, 'd')
    1203          e = SubElement(c, 'e')
    1204
    1205          self.assertEquals(
    1206              [b, d, c, e],
    1207              list(a.iterdescendants()))
    1208          self.assertEquals(
    1209              [],
    1210              list(d.iterdescendants()))
    1211
    1212 -    def test_iterdescendants_tag(self):
    1213          Element = self.etree.Element
    1214          SubElement = self.etree.SubElement
    1215
    1216          a = Element('a')
    1217          b = SubElement(a, 'b')
    1218          c = SubElement(a, 'c')
    1219          d = SubElement(b, 'd')
    1220          e = SubElement(c, 'e')
    1221
    1222          self.assertEquals(
    1223              [],
    1224              list(a.iterdescendants('a')))
    1225          a2 = SubElement(e, 'a')
    1226          self.assertEquals(
    1227              [a2],
    1228              list(a.iterdescendants('a')))
    1229          self.assertEquals(
    1230              [a2],
    1231              list(c.iterdescendants('a')))
    1232
    1233 -    def test_getroottree(self):
    1234          Element = self.etree.Element
    1235          SubElement = self.etree.SubElement
    1236
    1237          a = Element('a')
    1238          b = SubElement(a, 'b')
    1239          c = SubElement(a, 'c')
    1240          d = SubElement(b, 'd')
    1241          self.assertEquals(
    1242              a,
    1243              a.getroottree().getroot())
    1244          self.assertEquals(
    1245              a,
    1246              b.getroottree().getroot())
    1247          self.assertEquals(
    1248              a,
    1249              d.getroottree().getroot())
    1250
    1251 -    def test_getnext(self):
    1252          Element    = self.etree.Element
    1253          SubElement = self.etree.SubElement
    1254
    1255          a = Element('a')
    1256          b = SubElement(a, 'b')
    1257          c = SubElement(a, 'c')
    1258          self.assertEquals(
    1259              None,
    1260              a.getnext())
    1261          self.assertEquals(
    1262              c,
    1263              b.getnext())
    1264          self.assertEquals(
    1265              None,
    1266              c.getnext())
    1267
    1268 -    def test_getprevious(self):
    1269          Element    = self.etree.Element
    1270          SubElement = self.etree.SubElement
    1271
    1272          a = Element('a')
    1273          b = SubElement(a, 'b')
    1274          c = SubElement(a, 'c')
    1275          d = SubElement(b, 'd')
    1276          self.assertEquals(
    1277              None,
    1278              a.getprevious())
    1279          self.assertEquals(
    1280              b,
    1281              c.getprevious())
    1282          self.assertEquals(
    1283              None,
    1284              b.getprevious())
    1285
    1286 -    def test_itersiblings(self):
    1287          Element    = self.etree.Element
    1288          SubElement = self.etree.SubElement
    1289
    1290          a = Element('a')
    1291          b = SubElement(a, 'b')
    1292          c = SubElement(a, 'c')
    1293          d = SubElement(b, 'd')
    1294          self.assertEquals(
    1295              [],
    1296              list(a.itersiblings()))
    1297          self.assertEquals(
    1298              [c],
    1299              list(b.itersiblings()))
    1300          self.assertEquals(
    1301              [],
    1302              list(c.itersiblings()))
    1303          self.assertEquals(
    1304              [b],
    1305              list(c.itersiblings(preceding=True)))
    1306          self.assertEquals(
    1307              [],
    1308              list(b.itersiblings(preceding=True)))
    1309
    1310 -    def test_itersiblings_tag(self):
    1311          Element    = self.etree.Element
    1312          SubElement = self.etree.SubElement
    1313
    1314          a = Element('a')
    1315          b = SubElement(a, 'b')
    1316          c = SubElement(a, 'c')
    1317          d = SubElement(b, 'd')
    1318          self.assertEquals(
    1319              [],
    1320              list(a.itersiblings(tag='XXX')))
    1321          self.assertEquals(
    1322              [c],
    1323              list(b.itersiblings(tag='c')))
    1324          self.assertEquals(
    1325              [b],
    1326              list(c.itersiblings(preceding=True, tag='b')))
    1327          self.assertEquals(
    1328              [],
    1329              list(c.itersiblings(preceding=True, tag='c')))
    1330
    1331 -    def test_parseid(self):
    1332          parseid = self.etree.parseid
    1333          XML     = self.etree.XML
    1334          xml_text = _bytes('''
    1335          <!DOCTYPE document [
    1336          <!ELEMENT document (h1,p)*>
    1337          <!ELEMENT h1 (#PCDATA)>
    1338          <!ATTLIST h1 myid ID #REQUIRED>
    1339          <!ELEMENT p  (#PCDATA)>
    1340          <!ATTLIST p  someid ID #REQUIRED>
    1341          ]>
    1342          <document>
    1343            <h1 myid="chapter1">...</h1>
    1344            <p id="note1" class="note">...</p>
    1345            <p>Regular paragraph.</p>
    1346            <p xml:id="xmlid">XML:ID paragraph.</p>
    1347            <p someid="warn1" class="warning">...</p>
    1348          </document>
    1349          ''')
    1350
    1351          tree, dic = parseid(BytesIO(xml_text))
    1352          root = tree.getroot()
    1353          root2 = XML(xml_text)
    1354          self.assertEquals(self._writeElement(root),
    1355                            self._writeElement(root2))
    1356          expected = {
    1357              "chapter1" : root[0],
    1358              "xmlid"    : root[3],
    1359              "warn1"    : root[4]
    1360              }
    1361          self.assert_("chapter1" in dic)
    1362          self.assert_("warn1" in dic)
    1363          self.assert_("xmlid" in dic)
    1364          self._checkIDDict(dic, expected)
    1365
    1366 -    def test_XMLDTDID(self):
    1367          XMLDTDID = self.etree.XMLDTDID
    1368          XML      = self.etree.XML
    1369          xml_text = _bytes('''
    1370          <!DOCTYPE document [
    1371          <!ELEMENT document (h1,p)*>
    1372          <!ELEMENT h1 (#PCDATA)>
    1373          <!ATTLIST h1 myid ID #REQUIRED>
    1374          <!ELEMENT p  (#PCDATA)>
    1375          <!ATTLIST p  someid ID #REQUIRED>
    1376          ]>
    1377          <document>
    1378            <h1 myid="chapter1">...</h1>
    1379            <p id="note1" class="note">...</p>
    1380            <p>Regular paragraph.</p>
    1381            <p xml:id="xmlid">XML:ID paragraph.</p>
    1382            <p someid="warn1" class="warning">...</p>
    1383          </document>
    1384          ''')
    1385
    1386          root, dic = XMLDTDID(xml_text)
    1387          root2 = XML(xml_text)
    1388          self.assertEquals(self._writeElement(root),
    1389                            self._writeElement(root2))
    1390          expected = {
    1391              "chapter1" : root[0],
    1392              "xmlid"    : root[3],
    1393              "warn1"    : root[4]
    1394              }
    1395          self.assert_("chapter1" in dic)
    1396          self.assert_("warn1" in dic)
    1397          self.assert_("xmlid" in dic)
    1398          self._checkIDDict(dic, expected)
    1399
    1400 -    def test_XMLDTDID_empty(self):
    1401          XMLDTDID = self.etree.XMLDTDID
    1402          XML      = self.etree.XML
    1403          xml_text = _bytes('''
    1404          <document>
    1405            <h1 myid="chapter1">...</h1>
    1406            <p id="note1" class="note">...</p>
    1407            <p>Regular paragraph.</p>
    1408            <p someid="warn1" class="warning">...</p>
    1409          </document>
    1410          ''')
    1411
    1412          root, dic = XMLDTDID(xml_text)
    1413          root2 = XML(xml_text)
    1414          self.assertEquals(self._writeElement(root),
    1415                            self._writeElement(root2))
    1416          expected = {}
    1417          self._checkIDDict(dic, expected)
    1418
    1419 -    def _checkIDDict(self, dic, expected):
    1420          self.assertEquals(len(dic),
    1421                            len(expected))
    1422          self.assertEquals(sorted(dic.items()),
    1423                            sorted(expected.items()))
    1424          if sys.version_info < (3,):
    1425              self.assertEquals(sorted(dic.iteritems()),
    1426                                sorted(expected.iteritems()))
    1427          self.assertEquals(sorted(dic.keys()),
    1428                            sorted(expected.keys()))
    1429          if sys.version_info < (3,):
    1430              self.assertEquals(sorted(dic.iterkeys()),
    1431                                sorted(expected.iterkeys()))
    1432          if sys.version_info < (3,):
    1433              self.assertEquals(sorted(dic.values()),
    1434                                sorted(expected.values()))
    1435              self.assertEquals(sorted(dic.itervalues()),
    1436                                sorted(expected.itervalues()))
    1437
    1438 -    def test_namespaces(self):
    1439          etree = self.etree
    1440
    1441          r = {'foo': 'http://ns.infrae.com/foo'}
    1442          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1443          self.assertEquals(
    1444              'foo',
    1445              e.prefix)
    1446          self.assertEquals(
    1447              _bytes('<foo:bar xmlns:foo="http://ns.infrae.com/foo"></foo:bar>'),
    1448              self._writeElement(e))
    1449
    1450 -    def test_namespaces_default(self):
    1451          etree = self.etree
    1452
    1453          r = {None: 'http://ns.infrae.com/foo'}
    1454          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1455          self.assertEquals(
    1456              None,
    1457              e.prefix)
    1458          self.assertEquals(
    1459              '{http://ns.infrae.com/foo}bar',
    1460              e.tag)
    1461          self.assertEquals(
    1462              _bytes('<bar xmlns="http://ns.infrae.com/foo"></bar>'),
    1463              self._writeElement(e))
    1464
    1465 -    def test_namespaces_default_and_attr(self):
    1466          etree = self.etree
    1467
    1468          r = {None: 'http://ns.infrae.com/foo',
    1469               'hoi': 'http://ns.infrae.com/hoi'}
    1470          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1471          e.set('{http://ns.infrae.com/hoi}test', 'value')
    1472          self.assertEquals(
    1473              _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi" hoi:test="value"></bar>'),
    1474              self._writeElement(e))
    1475
    1476 -    def test_namespaces_elementtree(self):
    1477          etree = self.etree
    1478          r = {None: 'http://ns.infrae.com/foo',
    1479               'hoi': 'http://ns.infrae.com/hoi'}
    1480          e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r)
    1481          tree = etree.ElementTree(element=e)
    1482          etree.SubElement(e, '{http://ns.infrae.com/hoi}x')
    1483          self.assertEquals(
    1484              _bytes('<z xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi"><hoi:x></hoi:x></z>'),
    1485              self._writeElement(e))
    1486
    1487 -    def test_namespaces_default_copy_element(self):
    1488          etree = self.etree
    1489
    1490          r = {None: 'http://ns.infrae.com/foo'}
    1491          e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1492          e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1493
    1494          e1.append(e2)
    1495
    1496          self.assertEquals(
    1497              None,
    1498              e1.prefix)
    1499          self.assertEquals(
    1500              None,
    1501              e1[0].prefix)
    1502          self.assertEquals(
    1503              '{http://ns.infrae.com/foo}bar',
    1504              e1.tag)
    1505          self.assertEquals(
    1506              '{http://ns.infrae.com/foo}bar',
    1507              e1[0].tag)
    1508
    1509 -    def test_namespaces_copy_element(self):
    1510          etree = self.etree
    1511
    1512          r = {None: 'http://ns.infrae.com/BAR'}
    1513          e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r)
    1514          e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1515
    1516          e1.append(e2)
    1517
    1518          self.assertEquals(
    1519              None,
    1520              e1.prefix)
    1521          self.assertNotEquals(
    1522              None,
    1523              e2.prefix)
    1524          self.assertEquals(
    1525              '{http://ns.infrae.com/BAR}bar',
    1526              e1.tag)
    1527          self.assertEquals(
    1528              '{http://ns.infrae.com/foo}bar',
    1529              e2.tag)
    1530
    1531 -    def test_namespaces_reuse_after_move(self):
    1532          ns_href = "http://a.b.c"
    1533          one = self.etree.fromstring(
    1534              _bytes('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
    1535          baz = one[0][0]
    1536
    1537          two = self.etree.fromstring(
    1538              _bytes('<root xmlns:ns="%s"/>' % ns_href))
    1539          two.append(baz)
    1540          del one # make sure the source document is deallocated
    1541
    1542          self.assertEquals('{%s}baz' % ns_href, baz.tag)
    1543          self.assertEquals(
    1544              _bytes('<root xmlns:ns="%s"><ns:baz/></root>' % ns_href),
    1545              self.etree.tostring(two))
    1546
    1547 -    def test_namespace_cleanup(self):
    1548          xml = _bytes('<foo xmlns="F" xmlns:x="x"><bar xmlns:ns="NS" xmlns:b="b" xmlns="B"><ns:baz/></bar></foo>')
    1549          root = self.etree.fromstring(xml)
    1550          self.assertEquals(xml,
    1551                            self.etree.tostring(root))
    1552          self.etree.cleanup_namespaces(root)
    1553          self.assertEquals(
    1554              _bytes('<foo xmlns="F"><bar xmlns:ns="NS" xmlns="B"><ns:baz/></bar></foo>'),
    1555              self.etree.tostring(root))
    1556
    1557 -    def test_element_nsmap(self):
    1558          etree = self.etree
    1559
    1560          r = {None: 'http://ns.infrae.com/foo',
    1561               'hoi': 'http://ns.infrae.com/hoi'}
    1562          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    1563          self.assertEquals(
    1564              r,
    1565              e.nsmap)
    1566
    1567 -    def test_subelement_nsmap(self):
    1568          etree = self.etree
    1569
    1570          re = {None: 'http://ns.infrae.com/foo',
    1571               'hoi': 'http://ns.infrae.com/hoi'}
    1572          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re)
    1573
    1574          rs = {None: 'http://ns.infrae.com/honk',
    1575               'top': 'http://ns.infrae.com/top'}
    1576          s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs)
    1577
    1578          r = re.copy()
    1579          r.update(rs)
    1580          self.assertEquals(
    1581              re,
    1582              e.nsmap)
    1583          self.assertEquals(
    1584              r,
    1585              s.nsmap)
    1586
    1587 -    def test_getiterator_filter_namespace(self):
    1588          Element = self.etree.Element
    1589          SubElement = self.etree.SubElement
    1590
    1591          a = Element('{a}a')
    1592          b = SubElement(a, '{a}b')
    1593          c = SubElement(a, '{a}c')
    1594          d = SubElement(b, '{b}d')
    1595          e = SubElement(c, '{a}e')
    1596          f = SubElement(c, '{b}f')
    1597
    1598          self.assertEquals(
    1599              [a],
    1600              list(a.getiterator('{a}a')))
    1601          self.assertEquals(
    1602              [],
    1603              list(a.getiterator('{b}a')))
    1604          self.assertEquals(
    1605              [],
    1606              list(a.getiterator('a')))
    1607          self.assertEquals(
    1608              [f],
    1609              list(c.getiterator('{b}*')))
    1610          self.assertEquals(
    1611              [d, f],
    1612              list(a.getiterator('{b}*')))
    1613
    1614 -    def test_getiterator_filter_entities(self):
    1615          Element = self.etree.Element
    1616          Entity = self.etree.Entity
    1617          SubElement = self.etree.SubElement
    1618
    1619          a = Element('a')
    1620          b = SubElement(a, 'b')
    1621          entity_b = Entity("TEST-b")
    1622          b.append(entity_b)
    1623
    1624          self.assertEquals(
    1625              [entity_b],
    1626              list(a.getiterator(Entity)))
    1627
    1628          entity_a = Entity("TEST-a")
    1629          a.append(entity_a)
    1630
    1631          self.assertEquals(
    1632              [entity_b, entity_a],
    1633              list(a.getiterator(Entity)))
    1634
    1635          self.assertEquals(
    1636              [entity_b],
    1637              list(b.getiterator(Entity)))
    1638
    1639 -    def test_getiterator_filter_element(self):
    1640          Element = self.etree.Element
    1641          Comment = self.etree.Comment
    1642          PI = self.etree.PI
    1643          SubElement = self.etree.SubElement
    1644
    1645          a = Element('a')
    1646          b = SubElement(a, 'b')
    1647          a.append(Comment("test"))
    1648          a.append(PI("pi", "content"))
    1649          c = SubElement(a, 'c')
    1650
    1651          self.assertEquals(
    1652              [a, b, c],
    1653              list(a.getiterator(Element)))
    1654
    1655 -    def test_getiterator_filter_all_comment_pi(self):
    1656          # ElementTree iterates over everything here
    1657          Element = self.etree.Element
    1658          Comment = self.etree.Comment
    1659          PI = self.etree.PI
    1660          SubElement = self.etree.SubElement
    1661
    1662          a = Element('a')
    1663          b = SubElement(a, 'b')
    1664          a.append(Comment("test"))
    1665          a.append(PI("pi", "content"))
    1666          c = SubElement(a, 'c')
    1667
    1668          self.assertEquals(
    1669              [a, b, c],
    1670              list(a.getiterator('*')))
    1671
    1672 -    def test_elementtree_find_qname(self):
    1673          XML = self.etree.XML
    1674          ElementTree = self.etree.ElementTree
    1675          QName = self.etree.QName
    1676          tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
    1677          self.assertEquals(tree.find(QName("c")), tree.getroot()[2])
    1678
    1679 -    def test_elementtree_findall_qname(self):
    1680          XML = self.etree.XML
    1681          ElementTree = self.etree.ElementTree
    1682          QName = self.etree.QName
    1683          tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
    1684          self.assertEquals(len(list(tree.findall(QName("c")))), 1)
    1685
    1686 -    def test_elementtree_findall_ns_qname(self):
    1687          XML = self.etree.XML
    1688          ElementTree = self.etree.ElementTree
    1689          QName = self.etree.QName
    1690          tree = ElementTree(XML(
    1691                  _bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>')))
    1692          self.assertEquals(len(list(tree.findall(QName("b")))), 2)
    1693          self.assertEquals(len(list(tree.findall(QName("X", "b")))), 1)
    1694
    1695 -    def test_findall_ns(self):
    1696          XML = self.etree.XML
    1697          root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
    1698          self.assertEquals(len(root.findall(".//{X}b")), 2)
    1699          self.assertEquals(len(root.findall(".//{X}*")), 2)
    1700          self.assertEquals(len(root.findall(".//b")), 3)
    1701
    1702 -    def test_index(self):
    1703          etree = self.etree
    1704          e = etree.Element('foo')
    1705          for i in range(10):
    1706              etree.SubElement(e, 'a%s' % i)
    1707          for i in range(10):
    1708              self.assertEquals(
    1709                  i,
    1710                  e.index(e[i]))
    1711          self.assertEquals(
    1712              3, e.index(e[3], 3))
    1713          self.assertRaises(
    1714              ValueError, e.index, e[3], 4)
    1715          self.assertRaises(
    1716              ValueError, e.index, e[3], 0, 2)
    1717          self.assertRaises(
    1718              ValueError, e.index, e[8], 0, -3)
    1719          self.assertRaises(
    1720              ValueError, e.index, e[8], -5, -3)
    1721          self.assertEquals(
    1722              8, e.index(e[8], 0, -1))
    1723          self.assertEquals(
    1724              8, e.index(e[8], -12, -1))
    1725          self.assertEquals(
    1726              0, e.index(e[0], -12, -1))
    1727
    1728 -    def test_replace(self):
    1729          etree = self.etree
    1730          e = etree.Element('foo')
    1731          for i in range(10):
    1732              el = etree.SubElement(e, 'a%s' % i)
    1733              el.text = "text%d" % i
    1734              el.tail = "tail%d" % i
    1735
    1736          child0 = e[0]
    1737          child1 = e[1]
    1738          child2 = e[2]
    1739
    1740          e.replace(e[0], e[1])
    1741          self.assertEquals(
    1742              9, len(e))
    1743          self.assertEquals(
    1744              child1, e[0])
    1745          self.assertEquals(
    1746              child1.text, "text1")
    1747          self.assertEquals(
    1748              child1.tail, "tail1")
    1749          self.assertEquals(
    1750              child0.tail, "tail0")
    1751          self.assertEquals(
    1752              child2, e[1])
    1753
    1754          e.replace(e[-1], e[0])
    1755          self.assertEquals(
    1756              child1, e[-1])
    1757          self.assertEquals(
    1758              child1.text, "text1")
    1759          self.assertEquals(
    1760              child1.tail, "tail1")
    1761          self.assertEquals(
    1762              child2, e[0])
    1763
    1764 -    def test_replace_new(self):
    1765          etree = self.etree
    1766          e = etree.Element('foo')
    1767          for i in range(10):
    1768              etree.SubElement(e, 'a%s' % i)
    1769
    1770          new_element = etree.Element("test")
    1771          new_element.text = "TESTTEXT"
    1772          new_element.tail = "TESTTAIL"
    1773          child1 = e[1]
    1774          e.replace(e[0], new_element)
    1775          self.assertEquals(
    1776              new_element, e[0])
    1777          self.assertEquals(
    1778              "TESTTEXT",
    1779              e[0].text)
    1780          self.assertEquals(
    1781              "TESTTAIL",
    1782              e[0].tail)
    1783          self.assertEquals(
    1784              child1, e[1])
    1785
    1786 -    def test_setslice_all_empty_reversed(self):
    1787          Element = self.etree.Element
    1788          SubElement = self.etree.SubElement
    1789
    1790          a = Element('a')
    1791
    1792          e = Element('e')
    1793          f = Element('f')
    1794          g = Element('g')
    1795
    1796          s = [e, f, g]
    1797          a[::-1] = s
    1798          self.assertEquals(
    1799              [g, f, e],
    1800              list(a))
    1801
    1802 -    def test_setslice_step(self):
    1803          Element = self.etree.Element
    1804          SubElement = self.etree.SubElement
    1805
    1806          a = Element('a')
    1807          b = SubElement(a, 'b')
    1808          c = SubElement(a, 'c')
    1809          d = SubElement(a, 'd')
    1810          e = SubElement(a, 'e')
    1811
    1812          x = Element('x')
    1813          y = Element('y')
    1814
    1815          a[1::2] = [x, y]
    1816          self.assertEquals(
    1817              [b, x, d, y],
    1818              list(a))
    1819
    1820 -    def test_setslice_step_negative(self):
    1821          Element = self.etree.Element
    1822          SubElement = self.etree.SubElement
    1823
    1824          a = Element('a')
    1825          b = SubElement(a, 'b')
    1826          c = SubElement(a, 'c')
    1827          d = SubElement(a, 'd')
    1828          e = SubElement(a, 'e')
    1829
    1830          x = Element('x')
    1831          y = Element('y')
    1832
    1833          a[1::-1] = [x, y]
    1834          self.assertEquals(
    1835              [y, x, d, e],
    1836              list(a))
    1837
    1838 -    def test_setslice_step_negative2(self):
    1839          Element = self.etree.Element
    1840          SubElement = self.etree.SubElement
    1841
    1842          a = Element('a')
    1843          b = SubElement(a, 'b')
    1844          c = SubElement(a, 'c')
    1845          d = SubElement(a, 'd')
    1846          e = SubElement(a, 'e')
    1847
    1848          x = Element('x')
    1849          y = Element('y')
    1850
    1851          a[::-2] = [x, y]
    1852          self.assertEquals(
    1853              [b, y, d, x],
    1854              list(a))
    1855
    1856 -    def test_setslice_step_overrun(self):
    1857          Element = self.etree.Element
    1858          SubElement = self.etree.SubElement
    1859          try:
    1860              slice
    1861          except NameError:
    1862              print("slice() not found")
    1863              return
    1864
    1865          a = Element('a')
    1866          b = SubElement(a, 'b')
    1867          c = SubElement(a, 'c')
    1868          d = SubElement(a, 'd')
    1869          e = SubElement(a, 'e')
    1870
    1871          x = Element('x')
    1872          y = Element('y')
    1873          z = Element('z')
    1874
    1875          self.assertRaises(
    1876              ValueError,
    1877              operator.setitem, a, slice(1,None,2), [x, y, z])
    1878
    1879          self.assertEquals(
    1880              [b, c, d, e],
    1881              list(a))
    1882
    1883 -    def test_sourceline_XML(self):
    1884          XML = self.etree.XML
    1885          root = XML(_bytes('''<?xml version="1.0"?>
    1886          <root><test>
    1887
    1888          <bla/></test>
    1889          </root>
    1890          '''))
    1891
    1892          self.assertEquals(
    1893              [2, 2, 4],
    1894              [ el.sourceline for el in root.getiterator() ])
    1895
    1896 -    def test_sourceline_parse(self):
    1897          parse = self.etree.parse
    1898          tree = parse(fileInTestDir('include/test_xinclude.xml'))
    1899
    1900          self.assertEquals(
    1901              [1, 2, 3],
    1902              [ el.sourceline for el in tree.getiterator() ])
    1903
    1904 -    def test_sourceline_iterparse_end(self):
    1905          iterparse = self.etree.iterparse
    1906          lines = [ el.sourceline for (event, el) in
    1907                    iterparse(fileInTestDir('include/test_xinclude.xml')) ]
    1908
    1909          self.assertEquals(
    1910              [2, 3, 1],
    1911              lines)
    1912
    1913 -    def test_sourceline_iterparse_start(self):
    1914          iterparse = self.etree.iterparse
    1915          lines = [ el.sourceline for (event, el) in
    1916                    iterparse(fileInTestDir('include/test_xinclude.xml'),
    1917                              events=("start",)) ]
    1918
    1919          self.assertEquals(
    1920              [1, 2, 3],
    1921              lines)
    1922
    1923 -    def test_sourceline_element(self):
    1924          Element = self.etree.Element
    1925          SubElement = self.etree.SubElement
    1926          el = Element("test")
    1927          self.assertEquals(None, el.sourceline)
    1928
    1929          child = SubElement(el, "test")
    1930          self.assertEquals(None, el.sourceline)
    1931          self.assertEquals(None, child.sourceline)
    1932
    1933 -    def test_XML_base_url_docinfo(self):
    1934          etree = self.etree
    1935          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    1936          docinfo = root.getroottree().docinfo
    1937          self.assertEquals(docinfo.URL, "http://no/such/url")
    1938
    1939 -    def test_XML_set_base_url_docinfo(self):
    1940          etree = self.etree
    1941          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    1942          docinfo = root.getroottree().docinfo
    1943          self.assertEquals(docinfo.URL, "http://no/such/url")
    1944          docinfo.URL = "https://secret/url"
    1945          self.assertEquals(docinfo.URL, "https://secret/url")
    1946
    1947 -    def test_parse_stringio_base_url(self):
    1948          etree = self.etree
    1949          tree = etree.parse(BytesIO("<root/>"), base_url="http://no/such/url")
    1950          docinfo = tree.docinfo
    1951          self.assertEquals(docinfo.URL, "http://no/such/url")
    1952
    1953 -    def test_parse_base_url_docinfo(self):
    1954          etree = self.etree
    1955          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
    1956                             base_url="http://no/such/url")
    1957          docinfo = tree.docinfo
    1958          self.assertEquals(docinfo.URL, "http://no/such/url")
    1959
    1960 -    def test_HTML_base_url_docinfo(self):
    1961          etree = self.etree
    1962          root = etree.HTML(_bytes("<html/>"), base_url="http://no/such/url")
    1963          docinfo = root.getroottree().docinfo
    1964          self.assertEquals(docinfo.URL, "http://no/such/url")
    1965
    1966 -    def test_docinfo_public(self):
    1967          etree = self.etree
    1968          xml_header = '<?xml version="1.0" encoding="ascii"?>'
    1969          pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
    1970          sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    1971          doctype_string = '<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id)
    1972
    1973          xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
    1974
    1975          tree = etree.parse(BytesIO(xml))
    1976          docinfo = tree.docinfo
    1977          self.assertEquals(docinfo.encoding,    "ascii")
    1978          self.assertEquals(docinfo.xml_version, "1.0")
    1979          self.assertEquals(docinfo.public_id,   pub_id)
    1980          self.assertEquals(docinfo.system_url,  sys_id)
    1981          self.assertEquals(docinfo.root_name,   'html')
    1982          self.assertEquals(docinfo.doctype, doctype_string)
    1983
    1984 -    def test_docinfo_system(self):
    1985          etree = self.etree
    1986          xml_header = '<?xml version="1.0" encoding="UTF-8"?>'
    1987          sys_id = "some.dtd"
    1988          doctype_string = '<!DOCTYPE html SYSTEM "%s">' % sys_id
    1989          xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
    1990
    1991          tree = etree.parse(BytesIO(xml))
    1992          docinfo = tree.docinfo
    1993          self.assertEquals(docinfo.encoding,    "UTF-8")
    1994          self.assertEquals(docinfo.xml_version, "1.0")
    1995          self.assertEquals(docinfo.public_id,   None)
    1996          self.assertEquals(docinfo.system_url,  sys_id)
    1997          self.assertEquals(docinfo.root_name,   'html')
    1998          self.assertEquals(docinfo.doctype, doctype_string)
    1999
    2000 -    def test_docinfo_empty(self):
    2001          etree = self.etree
    2002          xml = _bytes('<html><body></body></html>')
    2003          tree = etree.parse(BytesIO(xml))
    2004          docinfo = tree.docinfo
    2005          self.assertEquals(docinfo.encoding,    "UTF-8")
    2006          self.assertEquals(docinfo.xml_version, "1.0")
    2007          self.assertEquals(docinfo.public_id,   None)
    2008          self.assertEquals(docinfo.system_url,  None)
    2009          self.assertEquals(docinfo.root_name,   'html')
    2010          self.assertEquals(docinfo.doctype, '')
    2011
    2012 -    def test_xml_base(self):
    2013          etree = self.etree
    2014          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    2015          self.assertEquals(root.base, "http://no/such/url")
    2016          self.assertEquals(
    2017              root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
    2018          root.base = "https://secret/url"
    2019          self.assertEquals(root.base, "https://secret/url")
    2020          self.assertEquals(
    2021              root.get('{http://www.w3.org/XML/1998/namespace}base'),
    2022              "https://secret/url")
    2023
    2024 -    def test_xml_base_attribute(self):
    2025          etree = self.etree
    2026          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    2027          self.assertEquals(root.base, "http://no/such/url")
    2028          self.assertEquals(
    2029              root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
    2030          root.set('{http://www.w3.org/XML/1998/namespace}base',
    2031                   "https://secret/url")
    2032          self.assertEquals(root.base, "https://secret/url")
    2033          self.assertEquals(
    2034              root.get('{http://www.w3.org/XML/1998/namespace}base'),
    2035              "https://secret/url")
    2036
    2037 -    def test_html_base(self):
    2038          etree = self.etree
    2039          root = etree.HTML(_bytes("<html><body></body></html>"),
    2040                            base_url="http://no/such/url")
    2041          self.assertEquals(root.base, "http://no/such/url")
    2042
    2043 -    def test_html_base_tag(self):
    2044          etree = self.etree
    2045          root = etree.HTML(_bytes('<html><head><base href="http://no/such/url"></head></html>'))
    2046          self.assertEquals(root.base, "http://no/such/url")
    2047
    2048 -    def test_parse_fileobject_unicode(self):
    2049          # parse from a file object that returns unicode strings
    2050          f = LargeFileLikeUnicode()
    2051          tree = self.etree.parse(f)
    2052          root = tree.getroot()
    2053          self.assert_(root.tag.endswith('root'))
    2054
    2055 -    def test_dtd_io(self):
    2056          # check that DTDs that go in also go back out
    2057          xml = _bytes('''\
    2058          <!DOCTYPE test SYSTEM "test.dtd" [
    2059            <!ENTITY entity "tasty">
    2060            <!ELEMENT test (a)>
    2061            <!ELEMENT a (#PCDATA)>
    2062          ]>
    2063          <test><a>test-test</a></test>\
    2064          ''')
    2065          tree = self.etree.parse(BytesIO(xml))
    2066          self.assertEqual(self.etree.tostring(tree).replace(_bytes(" "), _bytes("")),
    2067                           xml.replace(_bytes(" "), _bytes("")))
    2068
    2069 -    def test_byte_zero(self):
    2070          Element = self.etree.Element
    2071
    2072          a = Element('a')
    2073          self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho')
    2074          self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho')
    2075
    2076          self.assertRaises(ValueError, Element, 'ha\0ho')
    2077
    2078 -    def test_unicode_byte_zero(self):
    2079          Element = self.etree.Element
    2080
    2081          a = Element('a')
    2082          self.assertRaises(ValueError, setattr, a, "text",
    2083                            _str('ha\0ho'))
    2084          self.assertRaises(ValueError, setattr, a, "tail",
    2085                            _str('ha\0ho'))
    2086
    2087          self.assertRaises(ValueError, Element,
    2088                            _str('ha\0ho'))
    2089
    2090 -    def test_byte_invalid(self):
    2091          Element = self.etree.Element
    2092
    2093          a = Element('a')
    2094          self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho')
    2095          self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho')
    2096
    2097          self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho')
    2098          self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho')
    2099
    2100          self.assertRaises(ValueError, Element, 'ha\x07ho')
    2101          self.assertRaises(ValueError, Element, 'ha\x02ho')
    2102
    2103 -    def test_unicode_byte_invalid(self):
    2104          Element = self.etree.Element
    2105
    2106          a = Element('a')
    2107          self.assertRaises(ValueError, setattr, a, "text",
    2108                            _str('ha\x07ho'))
    2109          self.assertRaises(ValueError, setattr, a, "text",
    2110                            _str('ha\x02ho'))
    2111
    2112          self.assertRaises(ValueError, setattr, a, "tail",
    2113                            _str('ha\x07ho'))
    2114          self.assertRaises(ValueError, setattr, a, "tail",
    2115                            _str('ha\x02ho'))
    2116
    2117          self.assertRaises(ValueError, Element,
    2118                            _str('ha\x07ho'))
    2119          self.assertRaises(ValueError, Element,
    2120                            _str('ha\x02ho'))
    2121
    2122 -    def test_encoding_tostring_utf16(self):
    2123          # ElementTree fails to serialize this
    2124          tostring = self.etree.tostring
    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
    2132          result = tostring(a, encoding='UTF-16')
    2133          self.assertEquals(_bytes('<a><b></b><c></c></a>'),
    2134                            canonicalize(result))
    2135
    2136 -    def test_tostring_none(self):
    2137          # ElementTree raises an AssertionError here
    2138          tostring = self.etree.tostring
    2139          self.assertRaises(TypeError, self.etree.tostring, None)
    2140
    2141 -    def test_tostring_pretty(self):
    2142          tostring = self.etree.tostring
    2143          Element = self.etree.Element
    2144          SubElement = self.etree.SubElement
    2145
    2146          a = Element('a')
    2147          b = SubElement(a, 'b')
    2148          c = SubElement(a, 'c')
    2149
    2150          result = tostring(a)
    2151          self.assertEquals(result, _bytes("<a><b/><c/></a>"))
    2152
    2153          result = tostring(a, pretty_print=False)
    2154          self.assertEquals(result, _bytes("<a><b/><c/></a>"))
    2155
    2156          result = tostring(a, pretty_print=True)
    2157          self.assertEquals(result, _bytes("<a>\n  <b/>\n  <c/>\n</a>\n"))
    2158
    2159 -    def test_tostring_with_tail(self):
    2160          tostring = self.etree.tostring
    2161          Element = self.etree.Element
    2162          SubElement = self.etree.SubElement
    2163
    2164          a = Element('a')
    2165          a.tail = "aTAIL"
    2166          b = SubElement(a, 'b')
    2167          b.tail = "bTAIL"
    2168          c = SubElement(a, 'c')
    2169
    2170          result = tostring(a)
    2171          self.assertEquals(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
    2172
    2173          result = tostring(a, with_tail=False)
    2174          self.assertEquals(result, _bytes("<a><b/>bTAIL<c/></a>"))
    2175
    2176          result = tostring(a, with_tail=True)
    2177          self.assertEquals(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
    2178
    2179 -    def test_tostring_method_text_encoding(self):
    2180          tostring = self.etree.tostring
    2181          Element = self.etree.Element
    2182          SubElement = self.etree.SubElement
    2183
    2184          a = Element('a')
    2185          a.text = "A"
    2186          a.tail = "tail"
    2187          b = SubElement(a, 'b')
    2188          b.text = "B"
    2189          b.tail = _str("Søk på nettet")
    2190          c = SubElement(a, 'c')
    2191          c.text = "C"
    2192
    2193          result = tostring(a, method="text", encoding="UTF-16")
    2194
    2195          self.assertEquals(_str('ABSøk på nettetCtail').encode("UTF-16"),
    2196                            result)
    2197
    2198 -    def test_tostring_method_text_unicode(self):
    2199          tostring = self.etree.tostring
    2200          Element = self.etree.Element
    2201          SubElement = self.etree.SubElement
    2202
    2203          a = Element('a')
    2204          a.text = _str('Søk på nettetA')
    2205          a.tail = "tail"
    2206          b = SubElement(a, 'b')
    2207          b.text = "B"
    2208          b.tail = _str('Søk på nettetB')
    2209          c = SubElement(a, 'c')
    2210          c.text = "C"
    2211
    2212          self.assertRaises(UnicodeEncodeError,
    2213                            tostring, a, method="text")
    2214
    2215          self.assertEquals(
    2216              _str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'),
    2217              tostring(a, encoding="UTF-8", method="text"))
    2218
    2219 -    def test_tounicode(self):
    2220          tounicode = self.etree.tounicode
    2221          Element = self.etree.Element
    2222          SubElement = self.etree.SubElement
    2223
    2224          a = Element('a')
    2225          b = SubElement(a, 'b')
    2226          c = SubElement(a, 'c')
    2227
    2228          self.assert_(isinstance(tounicode(a), _unicode))
    2229          self.assertEquals(_bytes('<a><b></b><c></c></a>'),
    2230                            canonicalize(tounicode(a)))
    2231
    2232 -    def test_tounicode_element(self):
    2233          tounicode = self.etree.tounicode
    2234          Element = self.etree.Element
    2235          SubElement = self.etree.SubElement
    2236
    2237          a = Element('a')
    2238          b = SubElement(a, 'b')
    2239          c = SubElement(a, 'c')
    2240          d = SubElement(c, 'd')
    2241          self.assert_(isinstance(tounicode(b), _unicode))
    2242          self.assert_(isinstance(tounicode(c), _unicode))
    2243          self.assertEquals(_bytes('<b></b>'),
    2244                            canonicalize(tounicode(b)))
    2245          self.assertEquals(_bytes('<c><d></d></c>'),
    2246                            canonicalize(tounicode(c)))
    2247
    2248 -    def test_tounicode_none(self):
    2249          tounicode = self.etree.tounicode
    2250          self.assertRaises(TypeError, self.etree.tounicode, None)
    2251
    2252 -    def test_tounicode_element_tail(self):
    2253          tounicode = self.etree.tounicode
    2254          Element = self.etree.Element
    2255          SubElement = self.etree.SubElement
    2256
    2257          a = Element('a')
    2258          b = SubElement(a, 'b')
    2259          c = SubElement(a, 'c')
    2260          d = SubElement(c, 'd')
    2261          b.tail = 'Foo'
    2262
    2263          self.assert_(isinstance(tounicode(b), _unicode))
    2264          self.assert_(tounicode(b) == '<b/>Foo' or
    2265                       tounicode(b) == '<b />Foo')
    2266
    2267 -    def test_tounicode_pretty(self):
    2268          tounicode = self.etree.tounicode
    2269          Element = self.etree.Element
    2270          SubElement = self.etree.SubElement
    2271
    2272          a = Element('a')
    2273          b = SubElement(a, 'b')
    2274          c = SubElement(a, 'c')
    2275
    2276          result = tounicode(a)
    2277          self.assertEquals(result, "<a><b/><c/></a>")
    2278
    2279          result = tounicode(a, pretty_print=False)
    2280          self.assertEquals(result, "<a><b/><c/></a>")
    2281
    2282          result = tounicode(a, pretty_print=True)
    2283          self.assertEquals(result, "<a>\n  <b/>\n  <c/>\n</a>\n")
    2284
    2285 -    def test_tostring_unicode(self):
    2286          tostring = self.etree.tostring
    2287          Element = self.etree.Element
    2288          SubElement = self.etree.SubElement
    2289
    2290          a = Element('a')
    2291          b = SubElement(a, 'b')
    2292          c = SubElement(a, 'c')
    2293
    2294          self.assert_(isinstance(tostring(a, encoding=_unicode), _unicode))
    2295          self.assertEquals(_bytes('<a><b></b><c></c></a>'),
    2296                            canonicalize(tostring(a, encoding=_unicode)))
    2297
    2298 -    def test_tostring_unicode_element(self):
    2299          tostring = self.etree.tostring
    2300          Element = self.etree.Element
    2301          SubElement = self.etree.SubElement
    2302
    2303          a = Element('a')
    2304          b = SubElement(a, 'b')
    2305          c = SubElement(a, 'c')
    2306          d = SubElement(c, 'd')
    2307          self.assert_(isinstance(tostring(b, encoding=_unicode), _unicode))
    2308          self.assert_(isinstance(tostring(c, encoding=_unicode), _unicode))
    2309          self.assertEquals(_bytes('<b></b>'),
    2310                            canonicalize(tostring(b, encoding=_unicode)))
    2311          self.assertEquals(_bytes('<c><d></d></c>'),
    2312                            canonicalize(tostring(c, encoding=_unicode)))
    2313
    2314 -    def test_tostring_unicode_none(self):
    2315          tostring = self.etree.tostring
    2316          self.assertRaises(TypeError, self.etree.tostring,
    2317                            None, encoding=_unicode)
    2318
    2319 -    def test_tostring_unicode_element_tail(self):
    2320          tostring = self.etree.tostring
    2321          Element = self.etree.Element
    2322          SubElement = self.etree.SubElement
    2323
    2324          a = Element('a')
    2325          b = SubElement(a, 'b')
    2326          c = SubElement(a, 'c')
    2327          d = SubElement(c, 'd')
    2328          b.tail = 'Foo'
    2329
    2330          self.assert_(isinstance(tostring(b, encoding=_unicode), _unicode))
    2331          self.assert_(tostring(b, encoding=_unicode) == '<b/>Foo' or
    2332                       tostring(b, encoding=_unicode) == '<b />Foo')
    2333
    2334 -    def test_tostring_unicode_pretty(self):
    2335          tostring = self.etree.tostring
    2336          Element = self.etree.Element
    2337          SubElement = self.etree.SubElement
    2338
    2339          a = Element('a')
    2340          b = SubElement(a, 'b')
    2341          c = SubElement(a, 'c')
    2342
    2343          result = tostring(a, encoding=_unicode)
    2344          self.assertEquals(result, "<a><b/><c/></a>")
    2345
    2346          result = tostring(a, encoding=_unicode, pretty_print=False)
    2347          self.assertEquals(result, "<a><b/><c/></a>")
    2348
    2349          result = tostring(a, encoding=_unicode, pretty_print=True)
    2350          self.assertEquals(result, "<a>\n  <b/>\n  <c/>\n</a>\n")
    2351
    2352      # helper methods
    2353
    2354 -    def _writeElement(self, element, encoding='us-ascii'):
    2355          """Write out element for comparison.
    2356          """
    2357          ElementTree = self.etree.ElementTree
    2358          f = BytesIO()
    2359          tree = ElementTree(element=element)
    2360          tree.write(f, encoding=encoding)
    2361          data = f.getvalue()
    2362          return canonicalize(data)
    2363
    2364
    2365 -class XIncludeTestCase(HelperTestCase):
    2366 -    def test_xinclude_text(self):
    2367          filename = fileInTestDir('test_broken.xml')
    2368          root = etree.XML(_bytes('''\
    2369          <doc xmlns:xi="http://www.w3.org/2001/XInclude">
    2370            <xi:include href="%s" parse="text"/>
    2371          </doc>
    2372          ''' % filename))
    2373          old_text = root.text
    2374          content = open(filename).read()
    2375          old_tail = root[0].tail
    2376
    2377          self.include( etree.ElementTree(root) )
    2378          self.assertEquals(old_text + content + old_tail,
    2379                            root.text)
    2380
    2381 -    def test_xinclude(self):
    2382          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'))
    2383          self.assertNotEquals(
    2384              'a',
    2385              tree.getroot()[1].tag)
    2386          # process xincludes
    2387          self.include( tree )
    2388          # check whether we find it replaced with included data
    2389          self.assertEquals(
    2390              'a',
    2391              tree.getroot()[1].tag)
    2392
    2393 -    def test_xinclude_resolver(self):
    2394          class res(etree.Resolver):
    2395              include_text = open(fileInTestDir('test.xml')).read()
    2396              called = {}
    2397              def resolve(self, url, id, context):
    2398                  if url.endswith(".dtd"):
    2399                      self.called["dtd"] = True
    2400                      return self.resolve_filename(
    2401                          fileInTestDir('test.dtd'), context)
    2402                  elif url.endswith("test_xinclude.xml"):
    2403                      self.called["input"] = True
    2404                      return None # delegate to default resolver
    2405                  else:
    2406                      self.called["include"] = True
    2407                      return self.resolve_string(self.include_text, context)
    2408
    2409          res_instance = res()
    2410          parser = etree.XMLParser(load_dtd = True)
    2411          parser.resolvers.add(res_instance)
    2412
    2413          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
    2414                             parser = parser)
    2415
    2416          self.include(tree)
    2417
    2418          called = list(res_instance.called.items())
    2419          called.sort()
    2420          self.assertEquals(
    2421              [("dtd", True), ("include", True), ("input", True)],
    2422              called)
    2423
    2424 -class ETreeXIncludeTestCase(XIncludeTestCase):
    2425 -    def include(self, tree):
    2426          tree.xinclude()
    2427
    2428
    2429 -class ElementIncludeTestCase(XIncludeTestCase):
    2430      from lxml import ElementInclude
    2431 -    def include(self, tree):
    2432          self.ElementInclude.include(tree.getroot())
    2433
    2434
    2435 -class ETreeC14NTestCase(HelperTestCase):
    2436 -    def test_c14n(self):
    2437          tree = self.parse(_bytes('<a><b/></a>'))
    2438          f = BytesIO()
    2439          tree.write_c14n(f)
    2440          s = f.getvalue()
    2441          self.assertEquals(_bytes('<a><b></b></a>'),
    2442                            s)
    2443
    2444 -def test_suite():
    2445      suite = unittest.TestSuite()
    2446      suite.addTests([unittest.makeSuite(ETreeOnlyTestCase)])
    2447      suite.addTests([unittest.makeSuite(ETreeXIncludeTestCase)])
    2448      suite.addTests([unittest.makeSuite(ElementIncludeTestCase)])
    2449      suite.addTests([unittest.makeSuite(ETreeC14NTestCase)])
    2450      suite.addTests(
    2451          [make_doctest('../../../doc/tutorial.txt')])
    2452      suite.addTests(
    2453          [make_doctest('../../../doc/api.txt')])
    2454      suite.addTests(
    2455          [make_doctest('../../../doc/FAQ.txt')])
    2456      suite.addTests(
    2457          [make_doctest('../../../doc/parsing.txt')])
    2458      suite.addTests(
    2459          [make_doctest('../../../doc/resolvers.txt')])
    2460      return suite
    2461
    2462  if __name__ == '__main__':
    2463      print('to test use test.py %s' % __file__)
    2464