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