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

Source Code for Module lxml.tests.test_elementtree

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