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