# -*- coding: utf-8 -*- """ Tests for the ElementTree API Only test cases that apply equally well to etree and ElementTree belong here. Note that there is a second test module called test_io.py for IO related test cases. """ import unittest import os, re, tempfile, copy, operator, sys this_dir = os.path.dirname(__file__) if this_dir not in sys.path: sys.path.insert(0, this_dir) # needed for Py3 from common_imports import BytesIO, etree from common_imports import ElementTree, cElementTree, ET_VERSION, CET_VERSION from common_imports import filter_by_version, fileInTestDir, canonicalize, HelperTestCase from common_imports import _str, _bytes, unicode, next if cElementTree is not None and (CET_VERSION <= (1,0,7) or sys.version_info >= (3,3)): cElementTree = None if ElementTree is not None: print("Comparing with ElementTree %s" % getattr(ElementTree, "VERSION", "?")) if cElementTree is not None: print("Comparing with cElementTree %s" % getattr(cElementTree, "VERSION", "?")) class _ETreeTestCaseBase(HelperTestCase): etree = None required_versions_ET = {} required_versions_cET = {} def XMLParser(self, **kwargs): try: XMLParser = self.etree.XMLParser except AttributeError: assert 'ElementTree' in self.etree.__name__ XMLParser = self.etree.TreeBuilder return XMLParser(**kwargs) def test_element(self): for i in range(10): e = self.etree.Element('foo') self.assertEqual(e.tag, 'foo') self.assertEqual(e.text, None) self.assertEqual(e.tail, None) def test_simple(self): Element = self.etree.Element root = Element('root') root.append(Element('one')) root.append(Element('two')) root.append(Element('three')) self.assertEqual(3, len(root)) self.assertEqual('one', root[0].tag) self.assertEqual('two', root[1].tag) self.assertEqual('three', root[2].tag) self.assertRaises(IndexError, operator.getitem, root, 3) # test weird dictionary interaction leading to segfault previously def test_weird_dict_interaction(self): root = self.etree.Element('root') self.assertEqual(root.tag, "root") add = self.etree.ElementTree(file=BytesIO('Foo')) self.assertEqual(add.getroot().tag, "foo") self.assertEqual(add.getroot().text, "Foo") root.append(self.etree.Element('baz')) self.assertEqual(root.tag, "root") self.assertEqual(root[0].tag, "baz") def test_subelement(self): Element = self.etree.Element SubElement = self.etree.SubElement root = Element('root') SubElement(root, 'one') SubElement(root, 'two') SubElement(root, 'three') self.assertEqual(3, len(root)) self.assertEqual('one', root[0].tag) self.assertEqual('two', root[1].tag) self.assertEqual('three', root[2].tag) def test_element_contains(self): Element = self.etree.Element SubElement = self.etree.SubElement root1 = Element('root') SubElement(root1, 'one') self.assertTrue(root1[0] in root1) root2 = Element('root') SubElement(root2, 'two') SubElement(root2, 'three') self.assertTrue(root2[0] in root2) self.assertTrue(root2[1] in root2) self.assertFalse(root1[0] in root2) self.assertFalse(root2[0] in root1) self.assertFalse(None in root2) def test_element_indexing_with_text(self): ElementTree = self.etree.ElementTree f = BytesIO('TestOne') doc = ElementTree(file=f) root = doc.getroot() self.assertEqual(1, len(root)) self.assertEqual('one', root[0].tag) self.assertRaises(IndexError, operator.getitem, root, 1) def test_element_indexing_with_text2(self): ElementTree = self.etree.ElementTree f = BytesIO('OneTwohmThree') doc = ElementTree(file=f) root = doc.getroot() self.assertEqual(3, len(root)) self.assertEqual('one', root[0].tag) self.assertEqual('two', root[1].tag) self.assertEqual('three', root[2].tag) def test_element_indexing_only_text(self): ElementTree = self.etree.ElementTree f = BytesIO('Test') doc = ElementTree(file=f) root = doc.getroot() self.assertEqual(0, len(root)) def test_element_indexing_negative(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') self.assertEqual(d, a[-1]) self.assertEqual(c, a[-2]) self.assertEqual(b, a[-3]) self.assertRaises(IndexError, operator.getitem, a, -4) a[-1] = e = Element('e') self.assertEqual(e, a[-1]) del a[-1] self.assertEqual(2, len(a)) def test_elementtree(self): ElementTree = self.etree.ElementTree f = BytesIO('OneTwo') doc = ElementTree(file=f) root = doc.getroot() self.assertEqual(2, len(root)) self.assertEqual('one', root[0].tag) self.assertEqual('two', root[1].tag) def test_text(self): ElementTree = self.etree.ElementTree f = BytesIO('This is a text') doc = ElementTree(file=f) root = doc.getroot() self.assertEqual('This is a text', root.text) def test_text_empty(self): ElementTree = self.etree.ElementTree f = BytesIO('') doc = ElementTree(file=f) root = doc.getroot() self.assertEqual(None, root.text) def test_text_other(self): ElementTree = self.etree.ElementTree f = BytesIO('One') doc = ElementTree(file=f) root = doc.getroot() self.assertEqual(None, root.text) self.assertEqual('One', root[0].text) def test_text_escape_in(self): ElementTree = self.etree.ElementTree f = BytesIO('This is > than a text') doc = ElementTree(file=f) root = doc.getroot() self.assertEqual('This is > than a text', root.text) def test_text_escape_out(self): Element = self.etree.Element a = Element("a") a.text = "<>&" self.assertXML(_bytes('<>&'), a) def test_text_escape_tostring(self): tostring = self.etree.tostring Element = self.etree.Element a = Element("a") a.text = "<>&" self.assertEqual(_bytes('<>&'), tostring(a)) def test_text_str_subclass(self): Element = self.etree.Element class strTest(str): pass a = Element("a") a.text = strTest("text") self.assertXML(_bytes('text'), a) def test_tail(self): ElementTree = self.etree.ElementTree f = BytesIO('This is mixed content.') doc = ElementTree(file=f) root = doc.getroot() self.assertEqual(1, len(root)) self.assertEqual('This is ', root.text) self.assertEqual(None, root.tail) self.assertEqual('mixed', root[0].text) self.assertEqual(' content.', root[0].tail) def test_tail_str_subclass(self): Element = self.etree.Element SubElement = self.etree.SubElement class strTest(str): pass a = Element("a") SubElement(a, "t").tail = strTest("tail") self.assertXML(_bytes('tail'), a) def _test_del_tail(self): # this is discouraged for ET compat, should not be tested... XML = self.etree.XML root = XML(_bytes('This is mixed content.')) self.assertEqual(1, len(root)) self.assertEqual('This is ', root.text) self.assertEqual(None, root.tail) self.assertEqual('mixed', root[0].text) self.assertEqual(' content.', root[0].tail) del root[0].tail self.assertEqual(1, len(root)) self.assertEqual('This is ', root.text) self.assertEqual(None, root.tail) self.assertEqual('mixed', root[0].text) self.assertEqual(None, root[0].tail) root[0].tail = "TAIL" self.assertEqual(1, len(root)) self.assertEqual('This is ', root.text) self.assertEqual(None, root.tail) self.assertEqual('mixed', root[0].text) self.assertEqual('TAIL', root[0].tail) def test_ElementTree(self): Element = self.etree.Element ElementTree = self.etree.ElementTree el = Element('hoi') doc = ElementTree(el) root = doc.getroot() self.assertEqual(None, root.text) self.assertEqual('hoi', root.tag) def test_attrib(self): ElementTree = self.etree.ElementTree f = BytesIO('') doc = ElementTree(file=f) root = doc.getroot() self.assertEqual('One', root.attrib['one']) self.assertEqual('Two', root.attrib['two']) self.assertRaises(KeyError, operator.getitem, root.attrib, 'three') def test_attrib_get(self): ElementTree = self.etree.ElementTree f = BytesIO('') doc = ElementTree(file=f) root = doc.getroot() self.assertEqual('One', root.attrib.get('one')) self.assertEqual('Two', root.attrib.get('two')) self.assertEqual(None, root.attrib.get('three')) self.assertEqual('foo', root.attrib.get('three', 'foo')) def test_attrib_dict(self): ElementTree = self.etree.ElementTree f = BytesIO('') doc = ElementTree(file=f) root = doc.getroot() attrib = dict(root.attrib) self.assertEqual('One', attrib['one']) self.assertEqual('Two', attrib['two']) self.assertRaises(KeyError, operator.getitem, attrib, 'three') def test_attrib_copy(self): ElementTree = self.etree.ElementTree f = BytesIO('') doc = ElementTree(file=f) root = doc.getroot() attrib = copy.copy(root.attrib) self.assertEqual('One', attrib['one']) self.assertEqual('Two', attrib['two']) self.assertRaises(KeyError, operator.getitem, attrib, 'three') def test_attrib_deepcopy(self): ElementTree = self.etree.ElementTree f = BytesIO('') doc = ElementTree(file=f) root = doc.getroot() attrib = copy.deepcopy(root.attrib) self.assertEqual('One', attrib['one']) self.assertEqual('Two', attrib['two']) self.assertRaises(KeyError, operator.getitem, attrib, 'three') def test_attributes_get(self): ElementTree = self.etree.ElementTree f = BytesIO('') doc = ElementTree(file=f) root = doc.getroot() self.assertEqual('One', root.get('one')) self.assertEqual('Two', root.get('two')) self.assertEqual(None, root.get('three')) self.assertEqual('foo', root.get('three', 'foo')) def test_attrib_clear(self): XML = self.etree.XML root = XML(_bytes('')) self.assertEqual('One', root.get('one')) self.assertEqual('Two', root.get('two')) root.attrib.clear() self.assertEqual(None, root.get('one')) self.assertEqual(None, root.get('two')) def test_attrib_set_clear(self): Element = self.etree.Element root = Element("root", one="One") root.set("two", "Two") self.assertEqual('One', root.get('one')) self.assertEqual('Two', root.get('two')) root.attrib.clear() self.assertEqual(None, root.get('one')) self.assertEqual(None, root.get('two')) def test_attrib_ns_clear(self): Element = self.etree.Element SubElement = self.etree.SubElement attribNS = '{http://foo/bar}x' parent = Element('parent') parent.set(attribNS, 'a') child = SubElement(parent, 'child') child.set(attribNS, 'b') self.assertEqual('a', parent.get(attribNS)) self.assertEqual('b', child.get(attribNS)) parent.clear() self.assertEqual(None, parent.get(attribNS)) self.assertEqual('b', child.get(attribNS)) def test_attrib_pop(self): ElementTree = self.etree.ElementTree f = BytesIO('') doc = ElementTree(file=f) root = doc.getroot() self.assertEqual('One', root.attrib['one']) self.assertEqual('Two', root.attrib['two']) self.assertEqual('One', root.attrib.pop('one')) self.assertEqual(None, root.attrib.get('one')) self.assertEqual('Two', root.attrib['two']) def test_attrib_pop_unknown(self): root = self.etree.XML(_bytes('')) self.assertRaises(KeyError, root.attrib.pop, 'NONE') self.assertEqual('One', root.attrib['one']) self.assertEqual('Two', root.attrib['two']) def test_attrib_pop_default(self): root = self.etree.XML(_bytes('')) self.assertEqual('Three', root.attrib.pop('three', 'Three')) def test_attrib_pop_empty_default(self): root = self.etree.XML(_bytes('')) self.assertEqual('Three', root.attrib.pop('three', 'Three')) def test_attrib_pop_invalid_args(self): root = self.etree.XML(_bytes('')) self.assertRaises(TypeError, root.attrib.pop, 'One', None, None) def test_attribute_update_dict(self): XML = self.etree.XML root = XML(_bytes('')) items = list(root.attrib.items()) items.sort() self.assertEqual( [('alpha', 'Alpha'), ('beta', 'Beta')], items) root.attrib.update({'alpha' : 'test', 'gamma' : 'Gamma'}) items = list(root.attrib.items()) items.sort() self.assertEqual( [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')], items) def test_attribute_update_sequence(self): XML = self.etree.XML root = XML(_bytes('')) items = list(root.attrib.items()) items.sort() self.assertEqual( [('alpha', 'Alpha'), ('beta', 'Beta')], items) root.attrib.update({'alpha' : 'test', 'gamma' : 'Gamma'}.items()) items = list(root.attrib.items()) items.sort() self.assertEqual( [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')], items) def test_attribute_update_iter(self): XML = self.etree.XML root = XML(_bytes('')) items = list(root.attrib.items()) items.sort() self.assertEqual( [('alpha', 'Alpha'), ('beta', 'Beta')], items) root.attrib.update(iter({'alpha' : 'test', 'gamma' : 'Gamma'}.items())) items = list(root.attrib.items()) items.sort() self.assertEqual( [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')], items) def test_attribute_update_attrib(self): XML = self.etree.XML root = XML(_bytes('')) items = list(root.attrib.items()) items.sort() self.assertEqual( [('alpha', 'Alpha'), ('beta', 'Beta')], items) other = XML(_bytes('')) root.attrib.update(other.attrib) items = list(root.attrib.items()) items.sort() self.assertEqual( [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')], items) def test_attribute_keys(self): XML = self.etree.XML root = XML(_bytes('')) keys = list(root.attrib.keys()) keys.sort() self.assertEqual(['alpha', 'beta', 'gamma'], keys) def test_attribute_keys2(self): XML = self.etree.XML root = XML(_bytes('')) keys = list(root.keys()) keys.sort() self.assertEqual(['alpha', 'beta', 'gamma'], keys) def test_attribute_items2(self): XML = self.etree.XML root = XML(_bytes('')) items = list(root.items()) items.sort() self.assertEqual( [('alpha','Alpha'), ('beta','Beta'), ('gamma','Gamma')], items) def test_attribute_keys_ns(self): XML = self.etree.XML root = XML(_bytes('')) keys = list(root.keys()) keys.sort() self.assertEqual(['bar', '{http://ns.codespeak.net/test}baz'], keys) def test_attribute_values(self): XML = self.etree.XML root = XML(_bytes('')) values = list(root.attrib.values()) values.sort() self.assertEqual(['Alpha', 'Beta', 'Gamma'], values) def test_attribute_values_ns(self): XML = self.etree.XML root = XML(_bytes('')) values = list(root.attrib.values()) values.sort() self.assertEqual( ['Bar', 'Baz'], values) def test_attribute_items(self): XML = self.etree.XML root = XML(_bytes('')) items = list(root.attrib.items()) items.sort() self.assertEqual([ ('alpha', 'Alpha'), ('beta', 'Beta'), ('gamma', 'Gamma'), ], items) def test_attribute_items_ns(self): XML = self.etree.XML root = XML(_bytes('')) items = list(root.attrib.items()) items.sort() self.assertEqual( [('bar', 'Bar'), ('{http://ns.codespeak.net/test}baz', 'Baz')], items) def test_attribute_str(self): XML = self.etree.XML expected = "{'{http://ns.codespeak.net/test}baz': 'Baz', 'bar': 'Bar'}" alternative = "{'bar': 'Bar', '{http://ns.codespeak.net/test}baz': 'Baz'}" root = XML(_bytes('')) try: self.assertEqual(expected, str(root.attrib)) except AssertionError: self.assertEqual(alternative, str(root.attrib)) def test_attribute_contains(self): XML = self.etree.XML root = XML(_bytes('')) self.assertEqual( True, 'bar' in root.attrib) self.assertEqual( False, 'baz' in root.attrib) self.assertEqual( False, 'hah' in root.attrib) self.assertEqual( True, '{http://ns.codespeak.net/test}baz' in root.attrib) def test_attribute_set(self): Element = self.etree.Element root = Element("root") root.set("attr", "TEST") self.assertEqual("TEST", root.get("attr")) def test_attrib_as_attrib(self): Element = self.etree.Element root = Element("root") root.set("attr", "TEST") self.assertEqual("TEST", root.attrib["attr"]) root2 = Element("root2", root.attrib) self.assertEqual("TEST", root2.attrib["attr"]) def test_attribute_iterator(self): XML = self.etree.XML root = XML(_bytes('')) result = [] for key in root.attrib: result.append(key) result.sort() self.assertEqual(['alpha', 'beta', 'gamma'], result) def test_attribute_manipulation(self): Element = self.etree.Element a = Element('a') a.attrib['foo'] = 'Foo' a.attrib['bar'] = 'Bar' self.assertEqual('Foo', a.attrib['foo']) del a.attrib['foo'] self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo') def test_del_attribute_ns(self): Element = self.etree.Element a = Element('a') a.attrib['{http://a/}foo'] = 'Foo' a.attrib['{http://a/}bar'] = 'Bar' self.assertEqual(None, a.get('foo')) self.assertEqual('Foo', a.get('{http://a/}foo')) self.assertEqual('Foo', a.attrib['{http://a/}foo']) self.assertRaises(KeyError, operator.delitem, a.attrib, 'foo') self.assertEqual('Foo', a.attrib['{http://a/}foo']) del a.attrib['{http://a/}foo'] self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo') def test_del_attribute_ns_parsed(self): XML = self.etree.XML a = XML(_bytes('')) self.assertEqual('Foo', a.attrib['foo']) self.assertEqual('FooNS', a.attrib['{http://a/}foo']) del a.attrib['foo'] self.assertEqual('FooNS', a.attrib['{http://a/}foo']) self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo') self.assertRaises(KeyError, operator.delitem, a.attrib, 'foo') del a.attrib['{http://a/}foo'] self.assertRaises(KeyError, operator.getitem, a.attrib, '{http://a/}foo') self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo') a = XML(_bytes('')) self.assertEqual('Foo', a.attrib['foo']) self.assertEqual('FooNS', a.attrib['{http://a/}foo']) del a.attrib['foo'] self.assertEqual('FooNS', a.attrib['{http://a/}foo']) self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo') del a.attrib['{http://a/}foo'] self.assertRaises(KeyError, operator.getitem, a.attrib, '{http://a/}foo') self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo') def test_XML(self): XML = self.etree.XML root = XML(_bytes('This is a text.')) self.assertEqual(0, len(root)) self.assertEqual('This is a text.', root.text) def test_XMLID(self): XMLID = self.etree.XMLID XML = self.etree.XML xml_text = _bytes('''

...

...

Regular paragraph.

XML:ID paragraph.

...

''') root, dic = XMLID(xml_text) root2 = XML(xml_text) self.assertEqual(self._writeElement(root), self._writeElement(root2)) expected = { "chapter1" : root[0], "note1" : root[1], "warn1" : root[4] } self.assertEqual(dic, expected) def test_fromstring(self): fromstring = self.etree.fromstring root = fromstring('This is a text.') self.assertEqual(0, len(root)) self.assertEqual('This is a text.', root.text) required_versions_ET['test_fromstringlist'] = (1,3) def test_fromstringlist(self): fromstringlist = self.etree.fromstringlist root = fromstringlist(["T", "hi", "s is", " a text.<", "/doc", ">"]) self.assertEqual(0, len(root)) self.assertEqual('This is a text.', root.text) required_versions_ET['test_fromstringlist_characters'] = (1,3) def test_fromstringlist_characters(self): fromstringlist = self.etree.fromstringlist root = fromstringlist(list('This is a text.')) self.assertEqual(0, len(root)) self.assertEqual('This is a text.', root.text) required_versions_ET['test_fromstringlist_single'] = (1,3) def test_fromstringlist_single(self): fromstringlist = self.etree.fromstringlist root = fromstringlist(['This is a text.']) self.assertEqual(0, len(root)) self.assertEqual('This is a text.', root.text) def test_iselement(self): iselement = self.etree.iselement Element = self.etree.Element ElementTree = self.etree.ElementTree XML = self.etree.XML Comment = self.etree.Comment ProcessingInstruction = self.etree.ProcessingInstruction el = Element('hoi') self.assertTrue(iselement(el)) el2 = XML(_bytes('')) self.assertTrue(iselement(el2)) tree = ElementTree(element=Element('dag')) self.assertTrue(not iselement(tree)) self.assertTrue(iselement(tree.getroot())) c = Comment('test') self.assertTrue(iselement(c)) p = ProcessingInstruction("test", "some text") self.assertTrue(iselement(p)) def test_iteration(self): XML = self.etree.XML root = XML(_bytes('TwoHm')) result = [] for el in root: result.append(el.tag) self.assertEqual(['one', 'two', 'three'], result) def test_iteration_empty(self): XML = self.etree.XML root = XML(_bytes('')) result = [] for el in root: result.append(el.tag) self.assertEqual([], result) def test_iteration_text_only(self): XML = self.etree.XML root = XML(_bytes('Text')) result = [] for el in root: result.append(el.tag) self.assertEqual([], result) def test_iteration_crash(self): # this would cause a crash in the past fromstring = self.etree.fromstring root = etree.fromstring('

x') for elem in root: elem.tail = '' def test_iteration_reversed(self): XML = self.etree.XML root = XML(_bytes('TwoHm')) result = [] for el in reversed(root): result.append(el.tag) self.assertEqual(['three', 'two', 'one'], result) def test_iteration_subelement(self): XML = self.etree.XML root = XML(_bytes('TwoHm')) result = [] add = True for el in root: result.append(el.tag) if add: self.etree.SubElement(root, 'four') add = False self.assertEqual(['one', 'two', 'three', 'four'], result) def test_iteration_del_child(self): XML = self.etree.XML root = XML(_bytes('TwoHm')) result = [] for el in root: result.append(el.tag) del root[-1] self.assertEqual(['one', 'two'], result) def test_iteration_double(self): XML = self.etree.XML root = XML(_bytes('')) result = [] for el0 in root: result.append(el0.tag) for el1 in root: result.append(el1.tag) self.assertEqual(['one','one', 'two', 'two', 'one', 'two'], result) required_versions_ET['test_itertext'] = (1,3) def test_itertext(self): # ET 1.3+ XML = self.etree.XML root = XML(_bytes("RTEXT
ATAILCTEXTCTAIL")) text = list(root.itertext()) self.assertEqual(["RTEXT", "ATAIL", "CTEXT", "CTAIL"], text) required_versions_ET['test_itertext_child'] = (1,3) def test_itertext_child(self): # ET 1.3+ XML = self.etree.XML root = XML(_bytes("RTEXTATAILCTEXTCTAIL")) text = list(root[2].itertext()) self.assertEqual(["CTEXT"], text) def test_findall(self): XML = self.etree.XML root = XML(_bytes('')) self.assertEqual(len(list(root.findall("c"))), 1) self.assertEqual(len(list(root.findall(".//c"))), 2) self.assertEqual(len(list(root.findall(".//b"))), 3) self.assertEqual(len(list(root.findall(".//b"))[0]), 1) self.assertEqual(len(list(root.findall(".//b"))[1]), 0) self.assertEqual(len(list(root.findall(".//b"))[2]), 0) def test_findall_ns(self): XML = self.etree.XML root = XML(_bytes('')) self.assertEqual(len(list(root.findall(".//{X}b"))), 2) self.assertEqual(len(list(root.findall(".//b"))), 3) self.assertEqual(len(list(root.findall("b"))), 2) def test_element_with_attributes_keywords(self): Element = self.etree.Element el = Element('tag', foo='Foo', bar='Bar') self.assertEqual('Foo', el.attrib['foo']) self.assertEqual('Bar', el.attrib['bar']) def test_element_with_attributes(self): Element = self.etree.Element el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'}) self.assertEqual('Foo', el.attrib['foo']) self.assertEqual('Bar', el.attrib['bar']) def test_element_with_attributes_extra(self): Element = self.etree.Element el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'}, baz='Baz') self.assertEqual('Foo', el.attrib['foo']) self.assertEqual('Bar', el.attrib['bar']) self.assertEqual('Baz', el.attrib['baz']) def test_element_with_attributes_extra_duplicate(self): Element = self.etree.Element el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'}, bar='Baz') self.assertEqual('Foo', el.attrib['foo']) self.assertEqual('Baz', el.attrib['bar']) def test_element_with_attributes_ns(self): Element = self.etree.Element el = Element('tag', {'{ns1}foo':'Foo', '{ns2}bar':'Bar'}) self.assertEqual('Foo', el.attrib['{ns1}foo']) self.assertEqual('Bar', el.attrib['{ns2}bar']) def test_subelement_with_attributes(self): Element = self.etree.Element SubElement = self.etree.SubElement el = Element('tag') SubElement(el, 'foo', {'foo':'Foo'}, baz="Baz") self.assertEqual("Baz", el[0].attrib['baz']) self.assertEqual('Foo', el[0].attrib['foo']) def test_subelement_with_attributes_ns(self): Element = self.etree.Element SubElement = self.etree.SubElement el = Element('tag') SubElement(el, 'foo', {'{ns1}foo':'Foo', '{ns2}bar':'Bar'}) self.assertEqual('Foo', el[0].attrib['{ns1}foo']) self.assertEqual('Bar', el[0].attrib['{ns2}bar']) def test_write(self): ElementTree = self.etree.ElementTree XML = self.etree.XML for i in range(10): f = BytesIO() root = XML(_bytes('This is a test.' % (i, i))) tree = ElementTree(element=root) tree.write(f) data = f.getvalue() self.assertEqual( _bytes('This is a test.' % (i, i)), canonicalize(data)) required_versions_ET['test_write_method_html'] = (1,3) def test_write_method_html(self): ElementTree = self.etree.ElementTree Element = self.etree.Element SubElement = self.etree.SubElement html = Element('html') body = SubElement(html, 'body') p = SubElement(body, 'p') p.text = "html" SubElement(p, 'br').tail = "test" tree = ElementTree(element=html) f = BytesIO() tree.write(f, method="html") data = f.getvalue().replace(_bytes('\n'),_bytes('')) self.assertEqual(_bytes('

html
test

'), data) required_versions_ET['test_write_method_text'] = (1,3) def test_write_method_text(self): ElementTree = self.etree.ElementTree Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') a.text = "A" a.tail = "tail" b = SubElement(a, 'b') b.text = "B" b.tail = "TAIL" c = SubElement(a, 'c') c.text = "C" tree = ElementTree(element=a) f = BytesIO() tree.write(f, method="text") data = f.getvalue() self.assertEqual(_bytes('ABTAILCtail'), data) def test_write_fail(self): ElementTree = self.etree.ElementTree XML = self.etree.XML tree = ElementTree( XML(_bytes('This is a test.')) ) self.assertRaises(IOError, tree.write, "definitely////\\-\\nonexisting\\-\\////FILE") # this could trigger a crash, apparently because the document # reference was prematurely garbage collected def test_crash(self): Element = self.etree.Element element = Element('tag') for i in range(10): element.attrib['key'] = 'value' value = element.attrib['key'] self.assertEqual(value, 'value') # from doctest; for some reason this caused crashes too def test_write_ElementTreeDoctest(self): Element = self.etree.Element ElementTree = self.etree.ElementTree f = BytesIO() for i in range(10): element = Element('tag%s' % i) self._check_element(element) tree = ElementTree(element) tree.write(f) self._check_element_tree(tree) def test_subelement_reference(self): Element = self.etree.Element SubElement = self.etree.SubElement el = Element('foo') el2 = SubElement(el, 'bar') el3 = SubElement(el2, 'baz') al = Element('foo2') al2 = SubElement(al, 'bar2') al3 = SubElement(al2, 'baz2') # now move al2 into el el.append(al2) # now change al3 directly al3.text = 'baz2-modified' # it should have changed through this route too self.assertEqual( 'baz2-modified', el[1][0].text) def test_set_text(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') a.text = 'hoi' self.assertEqual( 'hoi', a.text) self.assertEqual( 'b', a[0].tag) def test_set_text2(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') a.text = 'hoi' b = SubElement(a ,'b') self.assertEqual( 'hoi', a.text) self.assertEqual( 'b', a[0].tag) def test_set_text_none(self): Element = self.etree.Element a = Element('a') a.text = 'foo' a.text = None self.assertEqual( None, a.text) self.assertXML(_bytes(''), a) def test_set_text_empty(self): Element = self.etree.Element a = Element('a') self.assertEqual(None, a.text) a.text = '' self.assertEqual('', a.text) self.assertXML(_bytes(''), a) def test_tail1(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') a.tail = 'dag' self.assertEqual('dag', a.tail) b = SubElement(a, 'b') b.tail = 'hoi' self.assertEqual('hoi', b.tail) self.assertEqual('dag', a.tail) def test_tail_append(self): Element = self.etree.Element a = Element('a') b = Element('b') b.tail = 'b_tail' a.append(b) self.assertEqual('b_tail', b.tail) def test_tail_set_twice(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') b.tail = 'foo' b.tail = 'bar' self.assertEqual('bar', b.tail) self.assertXML(_bytes('bar'), a) def test_tail_set_none(self): Element = self.etree.Element a = Element('a') a.tail = 'foo' a.tail = None self.assertEqual( None, a.tail) self.assertXML(_bytes(''), a) required_versions_ET['test_extend'] = (1,3) def test_extend(self): root = self.etree.Element('foo') for i in range(3): element = self.etree.SubElement(root, 'a%s' % i) element.text = "text%d" % i element.tail = "tail%d" % i elements = [] for i in range(3): new_element = self.etree.Element("test%s" % i) new_element.text = "TEXT%s" % i new_element.tail = "TAIL%s" % i elements.append(new_element) root.extend(elements) self.assertEqual( ["a0", "a1", "a2", "test0", "test1", "test2"], [ el.tag for el in root ]) self.assertEqual( ["text0", "text1", "text2", "TEXT0", "TEXT1", "TEXT2"], [ el.text for el in root ]) self.assertEqual( ["tail0", "tail1", "tail2", "TAIL0", "TAIL1", "TAIL2"], [ el.tail for el in root ]) def test_comment(self): Element = self.etree.Element SubElement = self.etree.SubElement Comment = self.etree.Comment a = Element('a') a.append(Comment('foo')) self.assertEqual(a[0].tag, Comment) self.assertEqual(a[0].text, 'foo') # ElementTree < 1.3 adds whitespace around comments required_versions_ET['test_comment_text'] = (1,3) def test_comment_text(self): Element = self.etree.Element SubElement = self.etree.SubElement Comment = self.etree.Comment tostring = self.etree.tostring a = Element('a') a.append(Comment('foo')) self.assertEqual(a[0].text, 'foo') self.assertEqual( _bytes(''), tostring(a)) a[0].text = "TEST" self.assertEqual(a[0].text, 'TEST') self.assertEqual( _bytes(''), tostring(a)) # ElementTree < 1.3 adds whitespace around comments required_versions_ET['test_comment_whitespace'] = (1,3) def test_comment_whitespace(self): Element = self.etree.Element SubElement = self.etree.SubElement Comment = self.etree.Comment tostring = self.etree.tostring a = Element('a') a.append(Comment(' foo ')) self.assertEqual(a[0].text, ' foo ') self.assertEqual( _bytes(''), tostring(a)) def test_comment_nonsense(self): Comment = self.etree.Comment c = Comment('foo') self.assertEqual({}, c.attrib) self.assertEqual([], list(c.keys())) self.assertEqual([], list(c.items())) self.assertEqual(None, c.get('hoi')) self.assertEqual(0, len(c)) # should not iterate for i in c: pass def test_pi(self): # lxml.etree separates target and text Element = self.etree.Element SubElement = self.etree.SubElement ProcessingInstruction = self.etree.ProcessingInstruction a = Element('a') a.append(ProcessingInstruction('foo', 'some more text')) self.assertEqual(a[0].tag, ProcessingInstruction) self.assertXML(_bytes(""), a) def test_processinginstruction(self): # lxml.etree separates target and text Element = self.etree.Element SubElement = self.etree.SubElement ProcessingInstruction = self.etree.PI a = Element('a') a.append(ProcessingInstruction('foo', 'some more text')) self.assertEqual(a[0].tag, ProcessingInstruction) self.assertXML(_bytes(""), a) def test_pi_nonsense(self): ProcessingInstruction = self.etree.ProcessingInstruction pi = ProcessingInstruction('foo') self.assertEqual({}, pi.attrib) self.assertEqual([], list(pi.keys())) self.assertEqual([], list(pi.items())) self.assertEqual(None, pi.get('hoi')) self.assertEqual(0, len(pi)) # should not iterate for i in pi: pass def test_setitem(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = Element('c') a[0] = c self.assertEqual( c, a[0]) self.assertXML(_bytes(''), a) self.assertXML(_bytes(''), b) def test_setitem2(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') for i in range(5): b = SubElement(a, 'b%s' % i) c = SubElement(b, 'c') for i in range(5): d = Element('d') e = SubElement(d, 'e') a[i] = d self.assertXML( _bytes(''), a) self.assertXML(_bytes(''), c) def test_setitem_replace(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') SubElement(a, 'b') d = Element('d') a[0] = d self.assertXML(_bytes(''), a) def test_setitem_indexerror(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') self.assertRaises(IndexError, operator.setitem, a, 1, Element('c')) def test_setitem_tail(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') b.tail = 'B2' c = Element('c') c.tail = 'C2' a[0] = c self.assertXML( _bytes('C2'), a) def test_tag_write(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') a.tag = 'c' self.assertEqual( 'c', a.tag) self.assertXML( _bytes(''), a) def test_tag_reset_ns(self): Element = self.etree.Element SubElement = self.etree.SubElement tostring = self.etree.tostring a = Element('{a}a') b1 = SubElement(a, '{a}b') b2 = SubElement(a, '{b}b') self.assertEqual('{a}b', b1.tag) b1.tag = 'c' # can't use C14N here! self.assertEqual('c', b1.tag) self.assertEqual(_bytes(''), a) def test_delitem(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') del a[1] self.assertXML( _bytes(''), a) del a[0] self.assertXML( _bytes(''), a) del a[0] self.assertXML( _bytes(''), a) # move deleted element into other tree afterwards other = Element('other') other.append(c) self.assertXML( _bytes(''), other) def test_del_insert(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') bs = SubElement(b, 'bs') c = SubElement(a, 'c') cs = SubElement(c, 'cs') el = a[0] self.assertXML( _bytes(''), a) self.assertXML(_bytes(''), b) self.assertXML(_bytes(''), c) del a[0] self.assertXML( _bytes(''), a) self.assertXML(_bytes(''), b) self.assertXML(_bytes(''), c) a.insert(0, el) self.assertXML( _bytes(''), a) self.assertXML(_bytes(''), b) self.assertXML(_bytes(''), c) def test_del_setitem(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') bs = SubElement(b, 'bs') c = SubElement(a, 'c') cs = SubElement(c, 'cs') el = a[0] del a[0] a[0] = el self.assertXML( _bytes(''), a) self.assertXML(_bytes(''), b) self.assertXML(_bytes(''), c) def test_del_setslice(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') bs = SubElement(b, 'bs') c = SubElement(a, 'c') cs = SubElement(c, 'cs') el = a[0] del a[0] a[0:0] = [el] self.assertXML( _bytes(''), a) self.assertXML(_bytes(''), b) self.assertXML(_bytes(''), c) def test_replace_slice_tail(self): XML = self.etree.XML a = XML(_bytes('B2C2')) b, c = a a[:] = [] self.assertEqual("B2", b.tail) self.assertEqual("C2", c.tail) def test_merge_namespaced_subtree_as_slice(self): XML = self.etree.XML root = XML(_bytes( '')) root[:] = root.findall('.//puh') # delete bar from hierarchy # previously, this lost a namespace declaration on bump2 result = self.etree.tostring(root) foo = self.etree.fromstring(result) self.assertEqual('puh', foo[0].tag) self.assertEqual('{http://huhu}bump1', foo[0][0].tag) self.assertEqual('{http://huhu}bump2', foo[0][1].tag) def test_delitem_tail(self): ElementTree = self.etree.ElementTree f = BytesIO('B2C2') doc = ElementTree(file=f) a = doc.getroot() del a[0] self.assertXML( _bytes('C2'), a) def test_clear(self): Element = self.etree.Element a = Element('a') a.text = 'foo' a.tail = 'bar' a.set('hoi', 'dag') a.clear() self.assertEqual(None, a.text) self.assertEqual(None, a.tail) self.assertEqual(None, a.get('hoi')) self.assertEqual('a', a.tag) def test_clear_sub(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') a.text = 'foo' a.tail = 'bar' a.set('hoi', 'dag') b = SubElement(a, 'b') c = SubElement(b, 'c') a.clear() self.assertEqual(None, a.text) self.assertEqual(None, a.tail) self.assertEqual(None, a.get('hoi')) self.assertEqual('a', a.tag) self.assertEqual(0, len(a)) self.assertXML(_bytes(''), a) self.assertXML(_bytes(''), b) def test_clear_tail(self): ElementTree = self.etree.ElementTree f = BytesIO('B2C2') doc = ElementTree(file=f) a = doc.getroot() a.clear() self.assertXML( _bytes(''), a) def test_insert(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = Element('d') a.insert(0, d) self.assertEqual( d, a[0]) self.assertXML( _bytes(''), a) e = Element('e') a.insert(2, e) self.assertEqual( e, a[2]) self.assertXML( _bytes(''), a) def test_insert_name_interning(self): # See GH#268 / LP#1773749. Element = self.etree.Element SubElement = self.etree.SubElement # Use unique names to make sure they are new in the tag name dict. import uuid names = dict((k, 'tag-' + str(uuid.uuid4())) for k in 'abcde') a = Element(names['a']) b = SubElement(a, names['b']) c = SubElement(a, names['c']) d = Element(names['d']) a.insert(0, d) self.assertEqual( d, a[0]) self.assertXML( _bytes('<%(a)s><%(d)s><%(b)s><%(c)s>' % names), a) e = Element(names['e']) a.insert(2, e) self.assertEqual( e, a[2]) self.assertXML( _bytes('<%(a)s><%(d)s><%(b)s><%(e)s><%(c)s>' % names), a) def test_insert_beyond_index(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = Element('c') a.insert(2, c) self.assertEqual( c, a[1]) self.assertXML( _bytes(''), a) def test_insert_negative(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = Element('d') a.insert(-1, d) self.assertEqual( d, a[-2]) self.assertXML( _bytes(''), a) def test_insert_tail(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = Element('c') c.tail = 'C2' a.insert(0, c) self.assertXML( _bytes('C2'), a) def test_remove(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') a.remove(b) self.assertEqual( c, a[0]) self.assertXML( _bytes(''), a) def test_remove_ns(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('{http://test}a') b = SubElement(a, '{http://test}b') c = SubElement(a, '{http://test}c') a.remove(b) self.assertXML( _bytes(''), a) self.assertXML( _bytes(''), b) def test_remove_nonexisting(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = Element('d') self.assertRaises( ValueError, a.remove, d) def test_remove_tail(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') b.tail = 'b2' a.remove(b) self.assertXML( _bytes(''), a) self.assertEqual('b2', b.tail) def _test_getchildren(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(b, 'd') e = SubElement(c, 'e') self.assertXML( _bytes(''), a) self.assertEqual( [b, c], a.getchildren()) self.assertEqual( [d], b.getchildren()) self.assertEqual( [], d.getchildren()) def test_makeelement(self): Element = self.etree.Element a = Element('a') b = a.makeelement('c', {'hoi':'dag'}) self.assertXML( _bytes(''), b) required_versions_ET['test_iter'] = (1,3) def test_iter(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(b, 'd') e = SubElement(c, 'e') self.assertEqual( [a, b, d, c, e], list(a.iter())) self.assertEqual( [d], list(d.iter())) def test_getiterator(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(b, 'd') e = SubElement(c, 'e') self.assertEqual( [a, b, d, c, e], list(a.getiterator())) self.assertEqual( [d], list(d.getiterator())) def test_getiterator_empty(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(b, 'd') e = SubElement(c, 'e') self.assertEqual( [], list(a.getiterator('none'))) self.assertEqual( [], list(e.getiterator('none'))) self.assertEqual( [e], list(e.getiterator())) def test_getiterator_filter(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(b, 'd') e = SubElement(c, 'e') self.assertEqual( [a], list(a.getiterator('a'))) a2 = SubElement(e, 'a') self.assertEqual( [a, a2], list(a.getiterator('a'))) self.assertEqual( [a2], list(c.getiterator('a'))) def test_getiterator_filter_all(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(b, 'd') e = SubElement(c, 'e') self.assertEqual( [a, b, d, c, e], list(a.getiterator('*'))) def test_getiterator_filter_comment(self): Element = self.etree.Element Comment = self.etree.Comment SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') comment_b = Comment("TEST-b") b.append(comment_b) self.assertEqual( [comment_b], list(a.getiterator(Comment))) comment_a = Comment("TEST-a") a.append(comment_a) self.assertEqual( [comment_b, comment_a], list(a.getiterator(Comment))) self.assertEqual( [comment_b], list(b.getiterator(Comment))) def test_getiterator_filter_pi(self): Element = self.etree.Element PI = self.etree.ProcessingInstruction SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') pi_b = PI("TEST-b") b.append(pi_b) self.assertEqual( [pi_b], list(a.getiterator(PI))) pi_a = PI("TEST-a") a.append(pi_a) self.assertEqual( [pi_b, pi_a], list(a.getiterator(PI))) self.assertEqual( [pi_b], list(b.getiterator(PI))) def test_getiterator_with_text(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') a.text = 'a' b = SubElement(a, 'b') b.text = 'b' b.tail = 'b1' c = SubElement(a, 'c') c.text = 'c' c.tail = 'c1' d = SubElement(b, 'd') c.text = 'd' c.tail = 'd1' e = SubElement(c, 'e') e.text = 'e' e.tail = 'e1' self.assertEqual( [a, b, d, c, e], list(a.getiterator())) #self.assertEqual( # [d], # list(d.getiterator())) def test_getiterator_filter_with_text(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') a.text = 'a' b = SubElement(a, 'b') b.text = 'b' b.tail = 'b1' c = SubElement(a, 'c') c.text = 'c' c.tail = 'c1' d = SubElement(b, 'd') c.text = 'd' c.tail = 'd1' e = SubElement(c, 'e') e.text = 'e' e.tail = 'e1' self.assertEqual( [a], list(a.getiterator('a'))) a2 = SubElement(e, 'a') self.assertEqual( [a, a2], list(a.getiterator('a'))) self.assertEqual( [a2], list(e.getiterator('a'))) def test_getslice(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') self.assertEqual( [b, c], a[0:2]) self.assertEqual( [b, c, d], a[:]) self.assertEqual( [b, c, d], a[:10]) self.assertEqual( [b], a[0:1]) self.assertEqual( [], a[10:12]) def test_getslice_negative(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') self.assertEqual( [d], a[-1:]) self.assertEqual( [c, d], a[-2:]) self.assertEqual( [c], a[-2:-1]) self.assertEqual( [b, c], a[-3:-1]) self.assertEqual( [b, c], a[-3:2]) def test_getslice_step(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') e = SubElement(a, 'e') self.assertEqual( [e,d,c,b], a[::-1]) self.assertEqual( [b,d], a[::2]) self.assertEqual( [e,c], a[::-2]) self.assertEqual( [d,c], a[-2:0:-1]) self.assertEqual( [e], a[:1:-2]) def test_getslice_text(self): ElementTree = self.etree.ElementTree f = BytesIO('BB1CC1') doc = ElementTree(file=f) a = doc.getroot() b = a[0] c = a[1] self.assertEqual( [b, c], a[:]) self.assertEqual( [b], a[0:1]) self.assertEqual( [c], a[1:]) def test_comment_getitem_getslice(self): Element = self.etree.Element Comment = self.etree.Comment SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') foo = Comment('foo') a.append(foo) c = SubElement(a, 'c') self.assertEqual( [b, foo, c], a[:]) self.assertEqual( foo, a[1]) a[1] = new = Element('new') self.assertEqual( new, a[1]) self.assertXML( _bytes(''), a) def test_delslice(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') e = SubElement(a, 'e') del a[1:3] self.assertEqual( [b, e], list(a)) def test_delslice_negative1(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') e = SubElement(a, 'e') del a[1:-1] self.assertEqual( [b, e], list(a)) def test_delslice_negative2(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') e = SubElement(a, 'e') del a[-3:-1] self.assertEqual( [b, e], list(a)) def test_delslice_step(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') e = SubElement(a, 'e') del a[1::2] self.assertEqual( [b, d], list(a)) def test_delslice_step_negative(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') e = SubElement(a, 'e') del a[::-1] self.assertEqual( [], list(a)) def test_delslice_step_negative2(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') e = SubElement(a, 'e') del a[::-2] self.assertEqual( [b, d], list(a)) def test_delslice_child_tail(self): ElementTree = self.etree.ElementTree f = BytesIO('B2C2D2E2') doc = ElementTree(file=f) a = doc.getroot() del a[1:3] self.assertXML( _bytes('B2E2'), a) def test_delslice_tail(self): XML = self.etree.XML a = XML(_bytes('B2C2')) b, c = a del a[:] self.assertEqual("B2", b.tail) self.assertEqual("C2", c.tail) def test_delslice_memory(self): # this could trigger a crash Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(b, 'c') del b # no more reference to b del a[:] self.assertEqual('c', c.tag) def test_setslice(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') e = Element('e') f = Element('f') g = Element('g') s = [e, f, g] a[1:2] = s self.assertEqual( [b, e, f, g, d], list(a)) def test_setslice_all(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') e = Element('e') f = Element('f') g = Element('g') s = [e, f, g] a[:] = s self.assertEqual( [e, f, g], list(a)) def test_setslice_all_empty(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') e = Element('e') f = Element('f') g = Element('g') s = [e, f, g] a[:] = s self.assertEqual( [e, f, g], list(a)) def test_setslice_all_replace(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') s = [b, c, d] a[:] = s self.assertEqual( [b, c, d], list(a)) def test_setslice_all_replace_reversed(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') s = [d, c, b] a[:] = s self.assertEqual( [d, c, b], list(a)) def test_setslice_all_replace_reversed_ns1(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('{ns}a') b = SubElement(a, '{ns}b', {'{ns1}a1': 'test'}) c = SubElement(a, '{ns}c', {'{ns2}a2': 'test'}) d = SubElement(a, '{ns}d', {'{ns3}a3': 'test'}) s = [d, c, b] a[:] = s self.assertEqual( [d, c, b], list(a)) self.assertEqual( ['{ns}d', '{ns}c', '{ns}b'], [ child.tag for child in a ]) self.assertEqual( [['{ns3}a3'], ['{ns2}a2'], ['{ns1}a1']], [ list(child.attrib.keys()) for child in a ]) def test_setslice_all_replace_reversed_ns2(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('{ns}a') b = SubElement(a, '{ns1}b', {'{ns}a1': 'test'}) c = SubElement(a, '{ns2}c', {'{ns}a2': 'test'}) d = SubElement(a, '{ns3}d', {'{ns}a3': 'test'}) s = [d, c, b] a[:] = s self.assertEqual( [d, c, b], list(a)) self.assertEqual( ['{ns3}d', '{ns2}c', '{ns1}b'], [ child.tag for child in a ]) self.assertEqual( [['{ns}a3'], ['{ns}a2'], ['{ns}a1']], [ list(child.attrib.keys()) for child in a ]) def test_setslice_end(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') e = Element('e') f = Element('f') g = Element('g') h = Element('h') s = [e, f] a[99:] = s self.assertEqual( [b, c, e, f], list(a)) s = [g, h] a[:0] = s self.assertEqual( [g, h, b, c, e, f], list(a)) def test_setslice_end_exact(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') e = Element('e') f = Element('f') g = Element('g') s = [e, f, g] a[3:] = s self.assertEqual( [b, c, d, e, f, g], list(a)) def test_setslice_single(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') e = Element('e') f = Element('f') s = [e] a[0:1] = s self.assertEqual( [e, c], list(a)) s = [f] a[1:2] = s self.assertEqual( [e, f], list(a)) def test_setslice_tail(self): ElementTree = self.etree.ElementTree Element = self.etree.Element f = BytesIO('B2C2D2E2') doc = ElementTree(file=f) a = doc.getroot() x = Element('x') y = Element('y') z = Element('z') x.tail = 'X2' y.tail = 'Y2' z.tail = 'Z2' a[1:3] = [x, y, z] self.assertXML( _bytes('B2X2Y2Z2E2'), a) def test_setslice_negative(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') x = Element('x') y = Element('y') a[1:-1] = [x, y] self.assertEqual( [b, x, y, d], list(a)) def test_setslice_negative2(self): Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(a, 'd') x = Element('x') y = Element('y') a[1:-2] = [x, y] self.assertEqual( [b, x, y, c, d], list(a)) def test_setslice_empty(self): Element = self.etree.Element a = Element('a') b = Element('b') c = Element('c') a[:] = [b, c] self.assertEqual( [b, c], list(a)) def test_tail_elementtree_root(self): Element = self.etree.Element ElementTree = self.etree.ElementTree a = Element('a') a.tail = 'A2' t = ElementTree(element=a) self.assertEqual('A2', a.tail) def test_elementtree_getiterator(self): Element = self.etree.Element SubElement = self.etree.SubElement ElementTree = self.etree.ElementTree a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(b, 'd') e = SubElement(c, 'e') t = ElementTree(element=a) self.assertEqual( [a, b, d, c, e], list(t.getiterator())) def test_elementtree_getiterator_filter(self): Element = self.etree.Element SubElement = self.etree.SubElement ElementTree = self.etree.ElementTree a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(b, 'd') e = SubElement(c, 'e') t = ElementTree(element=a) self.assertEqual( [a], list(t.getiterator('a'))) a2 = SubElement(e, 'a') self.assertEqual( [a, a2], list(t.getiterator('a'))) def test_ns_access(self): ElementTree = self.etree.ElementTree ns = 'http://xml.infrae.com/1' f = BytesIO('' % ns) t = ElementTree(file=f) a = t.getroot() self.assertEqual('{%s}a' % ns, a.tag) self.assertEqual('{%s}b' % ns, a[0].tag) def test_ns_access2(self): ElementTree = self.etree.ElementTree ns = 'http://xml.infrae.com/1' ns2 = 'http://xml.infrae.com/2' f = BytesIO('' % (ns, ns2)) t = ElementTree(file=f) a = t.getroot() self.assertEqual('{%s}a' % ns, a.tag) self.assertEqual('{%s}b' % ns, a[0].tag) self.assertEqual('{%s}b' % ns2, a[1].tag) def test_ns_setting(self): Element = self.etree.Element SubElement = self.etree.SubElement ns = 'http://xml.infrae.com/1' ns2 = 'http://xml.infrae.com/2' a = Element('{%s}a' % ns) b = SubElement(a, '{%s}b' % ns2) c = SubElement(a, '{%s}c' % ns) self.assertEqual('{%s}a' % ns, a.tag) self.assertEqual('{%s}b' % ns2, b.tag) self.assertEqual('{%s}c' % ns, c.tag) self.assertEqual('{%s}a' % ns, a.tag) self.assertEqual('{%s}b' % ns2, b.tag) self.assertEqual('{%s}c' % ns, c.tag) def test_ns_tag_parse(self): Element = self.etree.Element SubElement = self.etree.SubElement ElementTree = self.etree.ElementTree ns = 'http://xml.infrae.com/1' ns2 = 'http://xml.infrae.com/2' f = BytesIO('' % (ns, ns2)) t = ElementTree(file=f) a = t.getroot() self.assertEqual('{%s}a' % ns, a.tag) self.assertEqual('{%s}b' % ns2, a[0].tag) self.assertEqual('{%s}b' % ns, a[1].tag) def test_ns_attr(self): Element = self.etree.Element ns = 'http://xml.infrae.com/1' ns2 = 'http://xml.infrae.com/2' a = Element('a') a.set('{%s}foo' % ns, 'Foo') a.set('{%s}bar' % ns2, 'Bar') self.assertEqual( 'Foo', a.get('{%s}foo' % ns)) self.assertEqual( 'Bar', a.get('{%s}bar' % ns2)) try: self.assertXML( _bytes('' % (ns, ns2)), a) except AssertionError: self.assertXML( _bytes('' % (ns2, ns)), a) def test_ns_move(self): Element = self.etree.Element one = self.etree.fromstring( _bytes('')) baz = one[0][0] two = Element('root') two.append(baz) # removing the originating document could cause a crash/error before # as namespace is not moved along with it del one, baz self.assertEqual('{http://a.b.c}baz', two[0].tag) def test_ns_decl_tostring(self): tostring = self.etree.tostring root = self.etree.XML( _bytes('')) baz = root[0][0] nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"), tostring(baz)) self.assertEqual([_bytes("http://a.b.c")], nsdecl) def test_ns_decl_tostring_default(self): tostring = self.etree.tostring root = self.etree.XML( _bytes('')) baz = root[0][0] nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"), tostring(baz)) self.assertEqual([_bytes("http://a.b.c")], nsdecl) def test_ns_decl_tostring_root(self): tostring = self.etree.tostring root = self.etree.XML( _bytes('')) baz = root[0][0] nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"), tostring(baz)) self.assertEqual([_bytes("http://a.b.c")], nsdecl) def test_ns_decl_tostring_element(self): Element = self.etree.Element SubElement = self.etree.SubElement root = Element("foo") bar = SubElement(root, "{http://a.b.c}bar") baz = SubElement(bar, "{http://a.b.c}baz") nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"), self.etree.tostring(baz)) self.assertEqual([_bytes("http://a.b.c")], nsdecl) def test_attribute_xmlns_move(self): Element = self.etree.Element root = Element('element') subelement = Element('subelement', {"{http://www.w3.org/XML/1998/namespace}id": "foo"}) self.assertEqual(1, len(subelement.attrib)) self.assertEqual( "foo", subelement.get("{http://www.w3.org/XML/1998/namespace}id")) root.append(subelement) self.assertEqual(1, len(subelement.attrib)) self.assertEqual( list({"{http://www.w3.org/XML/1998/namespace}id" : "foo"}.items()), list(subelement.attrib.items())) self.assertEqual( "foo", subelement.get("{http://www.w3.org/XML/1998/namespace}id")) def test_namespaces_after_serialize(self): parse = self.etree.parse tostring = self.etree.tostring ns_href = "http://a.b.c" one = parse( BytesIO('' % ns_href)) baz = one.getroot()[0][0] parsed = parse(BytesIO( tostring(baz) )).getroot() self.assertEqual('{%s}baz' % ns_href, parsed.tag) def test_attribute_namespace_roundtrip(self): fromstring = self.etree.fromstring tostring = self.etree.tostring ns_href = "http://a.b.c" xml = _bytes('' % ( ns_href,ns_href)) root = fromstring(xml) self.assertEqual('test', root[0].get('{%s}a' % ns_href)) xml2 = tostring(root) self.assertTrue(_bytes(':a=') in xml2, xml2) root2 = fromstring(xml2) self.assertEqual('test', root2[0].get('{%s}a' % ns_href)) def test_attribute_namespace_roundtrip_replaced(self): fromstring = self.etree.fromstring tostring = self.etree.tostring ns_href = "http://a.b.c" xml = _bytes('' % ( ns_href,ns_href)) root = fromstring(xml) self.assertEqual('test', root[0].get('{%s}a' % ns_href)) root[0].set('{%s}a' % ns_href, 'TEST') xml2 = tostring(root) self.assertTrue(_bytes(':a=') in xml2, xml2) root2 = fromstring(xml2) self.assertEqual('TEST', root2[0].get('{%s}a' % ns_href)) required_versions_ET['test_register_namespace'] = (1,3) def test_register_namespace(self): # ET 1.3+ Element = self.etree.Element prefix = 'TESTPREFIX' namespace = 'http://seriously.unknown/namespace/URI' el = Element('{%s}test' % namespace) self.assertEqual(_bytes('' % namespace), self._writeElement(el)) self.etree.register_namespace(prefix, namespace) el = Element('{%s}test' % namespace) self.assertEqual(_bytes('<%s:test xmlns:%s="%s">' % ( prefix, prefix, namespace, prefix)), self._writeElement(el)) self.assertRaises(ValueError, self.etree.register_namespace, 'ns25', namespace) def test_tostring(self): tostring = self.etree.tostring Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') self.assertEqual(_bytes(''), canonicalize(tostring(a))) def test_tostring_element(self): tostring = self.etree.tostring Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(c, 'd') self.assertEqual(_bytes(''), canonicalize(tostring(b))) self.assertEqual(_bytes(''), canonicalize(tostring(c))) def test_tostring_element_tail(self): tostring = self.etree.tostring Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') b = SubElement(a, 'b') c = SubElement(a, 'c') d = SubElement(c, 'd') b.tail = 'Foo' self.assertTrue(tostring(b) == _bytes('Foo') or tostring(b) == _bytes('Foo')) required_versions_ET['test_tostring_method_html'] = (1,3) def test_tostring_method_html(self): tostring = self.etree.tostring Element = self.etree.Element SubElement = self.etree.SubElement html = Element('html') body = SubElement(html, 'body') p = SubElement(body, 'p') p.text = "html" SubElement(p, 'br').tail = "test" self.assertEqual(_bytes('

html
test

'), tostring(html, method="html")) required_versions_ET['test_tostring_method_text'] = (1,3) def test_tostring_method_text(self): tostring = self.etree.tostring Element = self.etree.Element SubElement = self.etree.SubElement a = Element('a') a.text = "A" a.tail = "tail" b = SubElement(a, 'b') b.text = "B" b.tail = "TAIL" c = SubElement(a, 'c') c.text = "C" self.assertEqual(_bytes('ABTAILCtail'), tostring(a, method="text")) def test_iterparse(self): iterparse = self.etree.iterparse f = BytesIO('') iterator = iterparse(f) self.assertEqual(None, iterator.root) events = list(iterator) root = iterator.root self.assertEqual( [('end', root[0]), ('end', root[1]), ('end', root)], events) def test_iterparse_incomplete(self): iterparse = self.etree.iterparse f = BytesIO('') iterator = iterparse(f) self.assertEqual(None, iterator.root) event, element = next(iter(iterator)) self.assertEqual('end', event) self.assertEqual('b', element.tag) def test_iterparse_file(self): iterparse = self.etree.iterparse iterator = iterparse(fileInTestDir("test.xml")) self.assertEqual(None, iterator.root) events = list(iterator) root = iterator.root self.assertEqual( [('end', root[0]), ('end', root)], events) def test_iterparse_start(self): iterparse = self.etree.iterparse f = BytesIO('') iterator = iterparse(f, events=('start',)) events = list(iterator) root = iterator.root self.assertEqual( [('start', root), ('start', root[0]), ('start', root[1])], events) def test_iterparse_start_end(self): iterparse = self.etree.iterparse f = BytesIO('') iterator = iterparse(f, events=('start','end')) events = list(iterator) root = iterator.root self.assertEqual( [('start', root), ('start', root[0]), ('end', root[0]), ('start', root[1]), ('end', root[1]), ('end', root)], events) def test_iterparse_clear(self): iterparse = self.etree.iterparse f = BytesIO('') iterator = iterparse(f) for event, elem in iterator: elem.clear() root = iterator.root self.assertEqual(0, len(root)) def test_iterparse_large(self): iterparse = self.etree.iterparse CHILD_COUNT = 12345 f = BytesIO('%s' % ('test'*CHILD_COUNT)) i = 0 for key in iterparse(f): event, element = key i += 1 self.assertEqual(i, CHILD_COUNT + 1) def test_iterparse_attrib_ns(self): iterparse = self.etree.iterparse f = BytesIO('') attr_name = '{http://testns/}bla' events = [] iterator = iterparse(f, events=('start','end','start-ns','end-ns')) for event, elem in iterator: events.append(event) if event == 'start': if elem.tag != '{http://ns1/}a': elem.set(attr_name, 'value') self.assertEqual( ['start-ns', 'start', 'start', 'start-ns', 'start', 'end', 'end-ns', 'end', 'end', 'end-ns'], events) root = iterator.root self.assertEqual( None, root.get(attr_name)) self.assertEqual( 'value', root[0].get(attr_name)) def test_iterparse_getiterator(self): iterparse = self.etree.iterparse f = BytesIO('') counts = [] for event, elem in iterparse(f): counts.append(len(list(elem.getiterator()))) self.assertEqual( [1,2,1,4], counts) def test_iterparse_move_elements(self): iterparse = self.etree.iterparse f = BytesIO('') for event, node in etree.iterparse(f): pass root = etree.Element('new_root', {}) root[:] = node[:] self.assertEqual( ['b', 'c'], [ el.tag for el in root ]) def test_iterparse_cdata(self): tostring = self.etree.tostring f = BytesIO('') context = self.etree.iterparse(f) content = [ el.text for event,el in context ] self.assertEqual(['test'], content) self.assertEqual(_bytes('test'), tostring(context.root)) def test_parse_file(self): parse = self.etree.parse # from file tree = parse(fileInTestDir('test.xml')) self.assertXML( _bytes(''), tree.getroot()) def test_parse_file_nonexistent(self): parse = self.etree.parse self.assertRaises(IOError, parse, fileInTestDir('notthere.xml')) def test_parse_error_none(self): parse = self.etree.parse self.assertRaises(TypeError, parse, None) required_versions_ET['test_parse_error'] = (1,3) def test_parse_error(self): # ET < 1.3 raises ExpatError parse = self.etree.parse f = BytesIO('') self.assertRaises(SyntaxError, parse, f) f.close() required_versions_ET['test_parse_error_from_file'] = (1,3) def test_parse_error_from_file(self): parse = self.etree.parse # from file f = open(fileInTestDir('test_broken.xml'), 'rb') self.assertRaises(SyntaxError, parse, f) f.close() def test_parse_file_object(self): parse = self.etree.parse # from file object f = open(fileInTestDir('test.xml'), 'rb') tree = parse(f) f.close() self.assertXML( _bytes(''), tree.getroot()) def test_parse_stringio(self): parse = self.etree.parse f = BytesIO('') tree = parse(f) f.close() self.assertXML( _bytes(''), tree.getroot() ) def test_parse_cdata(self): tostring = self.etree.tostring root = self.etree.XML(_bytes('')) self.assertEqual('test', root.text) self.assertEqual(_bytes('test'), tostring(root)) def test_parse_with_encoding(self): # this can fail in libxml2 <= 2.6.22 parse = self.etree.parse tree = parse(BytesIO('')) self.assertXML(_bytes(''), tree.getroot()) def test_encoding(self): Element = self.etree.Element a = Element('a') a.text = _str('Søk på nettet') self.assertXML( _str('Søk på nettet').encode('UTF-8'), a, 'utf-8') def test_encoding_exact(self): ElementTree = self.etree.ElementTree Element = self.etree.Element a = Element('a') a.text = _str('Søk på nettet') f = BytesIO() tree = ElementTree(element=a) tree.write(f, encoding='utf-8') self.assertEqual(_str('Søk på nettet').encode('UTF-8'), f.getvalue().replace(_bytes('\n'),_bytes(''))) def test_parse_file_encoding(self): parse = self.etree.parse # from file tree = parse(fileInTestDir('test-string.xml')) self.assertXML( _str('Søk på nettet').encode('UTF-8'), tree.getroot(), 'UTF-8') def test_parse_file_object_encoding(self): parse = self.etree.parse # from file object f = open(fileInTestDir('test-string.xml'), 'rb') tree = parse(f) f.close() self.assertXML( _str('Søk på nettet').encode('UTF-8'), tree.getroot(), 'UTF-8') def test_encoding_8bit_latin1(self): ElementTree = self.etree.ElementTree Element = self.etree.Element a = Element('a') a.text = _str('Søk på nettet') f = BytesIO() tree = ElementTree(element=a) tree.write(f, encoding='iso-8859-1') result = f.getvalue() declaration = _bytes("") self.assertEncodingDeclaration(result, _bytes('iso-8859-1')) result = result.split(_bytes('?>'), 1)[-1].replace(_bytes('\n'),_bytes('')) self.assertEqual(_str('Søk på nettet').encode('iso-8859-1'), result) required_versions_ET['test_parse_encoding_8bit_explicit'] = (1,3) def test_parse_encoding_8bit_explicit(self): XMLParser = self.XMLParser text = _str('Søk på nettet') xml_latin1 = (_str('%s') % text).encode('iso-8859-1') self.assertRaises(self.etree.ParseError, self.etree.parse, BytesIO(xml_latin1)) tree = self.etree.parse(BytesIO(xml_latin1), XMLParser(encoding="iso-8859-1")) a = tree.getroot() self.assertEqual(a.text, text) required_versions_ET['test_parse_encoding_8bit_override'] = (1,3) def test_parse_encoding_8bit_override(self): XMLParser = self.XMLParser text = _str('Søk på nettet') wrong_declaration = _str("") xml_latin1 = (_str('%s%s') % (wrong_declaration, text) ).encode('iso-8859-1') self.assertRaises(self.etree.ParseError, self.etree.parse, BytesIO(xml_latin1)) tree = self.etree.parse(BytesIO(xml_latin1), XMLParser(encoding="iso-8859-1")) a = tree.getroot() self.assertEqual(a.text, text) def _test_wrong_unicode_encoding(self): # raise error on wrong encoding declaration in unicode strings XML = self.etree.XML test_utf = (_str('') + _str('Søk på nettet')) self.assertRaises(SyntaxError, XML, test_utf) def test_encoding_write_default_encoding(self): ElementTree = self.etree.ElementTree Element = self.etree.Element a = Element('a') a.text = _str('Søk på nettet') f = BytesIO() tree = ElementTree(element=a) tree.write(f) data = f.getvalue().replace(_bytes('\n'),_bytes('')) self.assertEqual( _str('Søk på nettet').encode('ASCII', 'xmlcharrefreplace'), data) def test_encoding_tostring(self): Element = self.etree.Element tostring = self.etree.tostring a = Element('a') a.text = _str('Søk på nettet') self.assertEqual(_str('Søk på nettet').encode('UTF-8'), tostring(a, encoding='utf-8')) def test_encoding_tostring_unknown(self): Element = self.etree.Element tostring = self.etree.tostring a = Element('a') a.text = _str('Søk på nettet') self.assertRaises(LookupError, tostring, a, encoding='Invalid Encoding') def test_encoding_tostring_sub(self): Element = self.etree.Element SubElement = self.etree.SubElement tostring = self.etree.tostring a = Element('a') b = SubElement(a, 'b') b.text = _str('Søk på nettet') self.assertEqual(_str('Søk på nettet').encode('UTF-8'), tostring(b, encoding='utf-8')) def test_encoding_tostring_sub_tail(self): Element = self.etree.Element SubElement = self.etree.SubElement tostring = self.etree.tostring a = Element('a') b = SubElement(a, 'b') b.text = _str('Søk på nettet') b.tail = _str('Søk') self.assertEqual(_str('Søk på nettetSøk').encode('UTF-8'), tostring(b, encoding='utf-8')) def test_encoding_tostring_default_encoding(self): Element = self.etree.Element SubElement = self.etree.SubElement tostring = self.etree.tostring a = Element('a') a.text = _str('Søk på nettet') expected = _bytes('Søk på nettet') self.assertEqual( expected, tostring(a)) def test_encoding_sub_tostring_default_encoding(self): Element = self.etree.Element SubElement = self.etree.SubElement tostring = self.etree.tostring a = Element('a') b = SubElement(a, 'b') b.text = _str('Søk på nettet') expected = _bytes('Søk på nettet') self.assertEqual( expected, tostring(b)) def test_encoding_8bit_xml(self): utext = _str('Søk på nettet') uxml = _str('

%s

') % utext prologue = _bytes('') isoxml = prologue + uxml.encode('iso-8859-1') tree = self.etree.XML(isoxml) self.assertEqual(utext, tree.text) def test_encoding_utf8_bom(self): utext = _str('Søk på nettet') uxml = (_str('') + _str('

%s

') % utext) bom = _bytes('\\xEF\\xBB\\xBF').decode("unicode_escape").encode("latin1") xml = bom + uxml.encode("utf-8") tree = etree.XML(xml) self.assertEqual(utext, tree.text) def test_encoding_8bit_parse_stringio(self): utext = _str('Søk på nettet') uxml = _str('

%s

') % utext prologue = _bytes('') isoxml = prologue + uxml.encode('iso-8859-1') el = self.etree.parse(BytesIO(isoxml)).getroot() self.assertEqual(utext, el.text) def test_deepcopy_elementtree(self): Element = self.etree.Element ElementTree = self.etree.ElementTree a = Element('a') a.text = "Foo" atree = ElementTree(a) btree = copy.deepcopy(atree) self.assertEqual("Foo", atree.getroot().text) self.assertEqual("Foo", btree.getroot().text) self.assertFalse(btree is atree) self.assertFalse(btree.getroot() is atree.getroot()) def test_deepcopy(self): Element = self.etree.Element a = Element('a') a.text = 'Foo' b = copy.deepcopy(a) self.assertEqual('Foo', b.text) b.text = 'Bar' self.assertEqual('Bar', b.text) self.assertEqual('Foo', a.text) del a self.assertEqual('Bar', b.text) def test_deepcopy_tail(self): Element = self.etree.Element a = Element('a') a.tail = 'Foo' b = copy.deepcopy(a) self.assertEqual('Foo', b.tail) b.tail = 'Bar' self.assertEqual('Bar', b.tail) self.assertEqual('Foo', a.tail) del a self.assertEqual('Bar', b.tail) def test_deepcopy_subelement(self): Element = self.etree.Element SubElement = self.etree.SubElement root = Element('root') a = SubElement(root, 'a') a.text = 'FooText' a.tail = 'FooTail' b = copy.deepcopy(a) self.assertEqual('FooText', b.text) self.assertEqual('FooTail', b.tail) b.text = 'BarText' b.tail = 'BarTail' self.assertEqual('BarTail', b.tail) self.assertEqual('FooTail', a.tail) self.assertEqual('BarText', b.text) self.assertEqual('FooText', a.text) del a self.assertEqual('BarTail', b.tail) self.assertEqual('BarText', b.text) def test_deepcopy_namespaces(self): root = self.etree.XML(_bytes(''' ''')) self.assertEqual( root[0][0].get('{tns}foo'), copy.deepcopy(root[0])[0].get('{tns}foo') ) self.assertEqual( root[0][0].get('{tns}foo'), copy.deepcopy(root[0][0]).get('{tns}foo') ) def test_deepcopy_append(self): # previously caused a crash Element = self.etree.Element tostring = self.etree.tostring a = Element('a') b = copy.deepcopy(a) a.append( Element('C') ) b.append( Element('X') ) self.assertEqual(_bytes(''), tostring(a).replace(_bytes(' '), _bytes(''))) self.assertEqual(_bytes(''), tostring(b).replace(_bytes(' '), _bytes(''))) def test_deepcopy_comment(self): # previously caused a crash # not supported by ET < 1.3! Comment = self.etree.Comment a = Comment("ONE") b = copy.deepcopy(a) b.text = "ANOTHER" self.assertEqual('ONE', a.text) self.assertEqual('ANOTHER', b.text) def test_shallowcopy(self): Element = self.etree.Element a = Element('a') a.text = 'Foo' b = copy.copy(a) self.assertEqual('Foo', b.text) b.text = 'Bar' self.assertEqual('Bar', b.text) self.assertEqual('Foo', a.text) # XXX ElementTree will share nodes, but lxml.etree won't.. def test_shallowcopy_elementtree(self): Element = self.etree.Element ElementTree = self.etree.ElementTree a = Element('a') a.text = 'Foo' atree = ElementTree(a) btree = copy.copy(atree) self.assertFalse(btree is atree) self.assertTrue(btree.getroot() is atree.getroot()) self.assertEqual('Foo', atree.getroot().text) def _test_element_boolean(self): # deprecated as of ET 1.3/lxml 2.0 etree = self.etree e = etree.Element('foo') self.assertEqual(False, bool(e)) etree.SubElement(e, 'bar') self.assertEqual(True, bool(e)) e = etree.Element('foo') e.text = 'hey' self.assertEqual(False, bool(e)) e = etree.Element('foo') e.tail = 'bar' self.assertEqual(False, bool(e)) e = etree.Element('foo') e.set('bar', 'Bar') self.assertEqual(False, bool(e)) def test_multiple_elementrees(self): etree = self.etree a = etree.Element('a') b = etree.SubElement(a, 'b') t = etree.ElementTree(a) self.assertEqual(self._rootstring(t), _bytes('')) t1 = etree.ElementTree(a) self.assertEqual(self._rootstring(t1), _bytes('')) self.assertEqual(self._rootstring(t), _bytes('')) t2 = etree.ElementTree(b) self.assertEqual(self._rootstring(t2), _bytes('')) self.assertEqual(self._rootstring(t1), _bytes('')) self.assertEqual(self._rootstring(t), _bytes('')) def test_qname(self): etree = self.etree qname = etree.QName('myns', 'a') a1 = etree.Element(qname) a2 = etree.SubElement(a1, qname) self.assertEqual(a1.tag, "{myns}a") self.assertEqual(a2.tag, "{myns}a") def test_qname_cmp(self): etree = self.etree qname1 = etree.QName('myns', 'a') qname2 = etree.QName('myns', 'a') self.assertEqual(qname1, "{myns}a") self.assertEqual("{myns}a", qname2) self.assertEqual(qname1, qname1) self.assertEqual(qname1, qname2) def test_qname_attribute_getset(self): etree = self.etree qname = etree.QName('myns', 'a') a = etree.Element(qname) a.set(qname, "value") self.assertEqual(a.get(qname), "value") self.assertEqual(a.get("{myns}a"), "value") def test_qname_attrib(self): etree = self.etree qname = etree.QName('myns', 'a') a = etree.Element(qname) a.attrib[qname] = "value" self.assertEqual(a.attrib[qname], "value") self.assertEqual(a.attrib.get(qname), "value") self.assertEqual(a.attrib["{myns}a"], "value") self.assertEqual(a.attrib.get("{myns}a"), "value") def test_qname_attribute_resolve(self): etree = self.etree qname = etree.QName('http://myns', 'a') a = etree.Element(qname) a.set(qname, qname) self.assertXML( _bytes(''), a) def test_qname_attribute_resolve_new(self): etree = self.etree qname = etree.QName('http://myns', 'a') a = etree.Element('a') a.set('a', qname) self.assertXML( _bytes(''), a) def test_qname_attrib_resolve(self): etree = self.etree qname = etree.QName('http://myns', 'a') a = etree.Element(qname) a.attrib[qname] = qname self.assertXML( _bytes(''), a) def test_parser_version(self): etree = self.etree parser = etree.XMLParser() if hasattr(parser, "version"): # ElementTree 1.3+, cET self.assertTrue(re.match("[^ ]+ [0-9.]+", parser.version)) # feed parser interface def test_feed_parser_bytes(self): parser = self.XMLParser() parser.feed(_bytes('<')) parser.feed(_bytes('a test="works"/')) parser.feed(_bytes('>')) root = parser.close() self.assertEqual(root.tag, "root") self.assertEqual(root[0].tag, "a") self.assertEqual(root[0].get("test"), "works") def test_feed_parser_unicode(self): parser = self.XMLParser() parser.feed(_str('<')) parser.feed(_str('a test="works"/')) parser.feed(_str('>')) root = parser.close() self.assertEqual(root.tag, "root") self.assertEqual(root[0].tag, "a") self.assertEqual(root[0].get("test"), "works") required_versions_ET['test_feed_parser_error_close_empty'] = (1,3) def test_feed_parser_error_close_empty(self): ParseError = self.etree.ParseError parser = self.XMLParser() self.assertRaises(ParseError, parser.close) required_versions_ET['test_feed_parser_error_close_incomplete'] = (1,3) def test_feed_parser_error_close_incomplete(self): ParseError = self.etree.ParseError parser = self.XMLParser() parser.feed('<><><><><><') except ParseError: # can raise, but not required before close() pass self.assertRaises(ParseError, parser.close) required_versions_ET['test_feed_parser_error_position'] = (1,3) def test_feed_parser_error_position(self): ParseError = self.etree.ParseError parser = self.XMLParser() try: parser.close() except ParseError: e = sys.exc_info()[1] self.assertNotEqual(None, e.code) self.assertNotEqual(0, e.code) self.assertTrue(isinstance(e.position, tuple)) self.assertTrue(e.position >= (0, 0)) # parser target interface required_versions_ET['test_parser_target_property'] = (1,3) def test_parser_target_property(self): class Target(object): pass target = Target() parser = self.XMLParser(target=target) self.assertEqual(target, parser.target) def test_parser_target_tag(self): assertEqual = self.assertEqual assertFalse = self.assertFalse events = [] class Target(object): def start(self, tag, attrib): events.append("start") assertFalse(attrib) assertEqual("TAG", tag) def end(self, tag): events.append("end") assertEqual("TAG", tag) def close(self): return "DONE" parser = self.XMLParser(target=Target()) parser.feed("") done = parser.close() self.assertEqual("DONE", done) self.assertEqual(["start", "end"], events) def test_parser_target_error_in_start(self): assertEqual = self.assertEqual events = [] class Target(object): def start(self, tag, attrib): events.append("start") assertEqual("TAG", tag) raise ValueError("TEST") def end(self, tag): events.append("end") assertEqual("TAG", tag) def close(self): return "DONE" parser = self.XMLParser(target=Target()) try: parser.feed("") except ValueError: self.assertTrue('TEST' in str(sys.exc_info()[1])) else: self.assertTrue(False) if 'lxml' in self.etree.__name__: self.assertEqual(["start"], events) else: # cElementTree calls end() as well self.assertTrue("start" in events) def test_parser_target_error_in_end(self): assertEqual = self.assertEqual events = [] class Target(object): def start(self, tag, attrib): events.append("start") assertEqual("TAG", tag) def end(self, tag): events.append("end") assertEqual("TAG", tag) raise ValueError("TEST") def close(self): return "DONE" parser = self.XMLParser(target=Target()) try: parser.feed("") except ValueError: self.assertTrue('TEST' in str(sys.exc_info()[1])) else: self.assertTrue(False) self.assertEqual(["start", "end"], events) def test_parser_target_error_in_close(self): assertEqual = self.assertEqual events = [] class Target(object): def start(self, tag, attrib): events.append("start") assertEqual("TAG", tag) def end(self, tag): events.append("end") assertEqual("TAG", tag) def close(self): raise ValueError("TEST") parser = self.XMLParser(target=Target()) try: parser.feed("") parser.close() except ValueError: self.assertTrue('TEST' in str(sys.exc_info()[1])) else: self.assertTrue(False) self.assertEqual(["start", "end"], events) def test_parser_target_error_in_start_and_close(self): assertEqual = self.assertEqual events = [] class Target(object): def start(self, tag, attrib): events.append("start") assertEqual("TAG", tag) raise IndexError("TEST-IE") def end(self, tag): events.append("end") assertEqual("TAG", tag) def close(self): raise ValueError("TEST-VE") parser = self.XMLParser(target=Target()) try: parser.feed("") parser.close() except IndexError: if 'lxml' in self.etree.__name__: # we try not to swallow the initial exception in Py2 self.assertTrue(sys.version_info[0] < 3) self.assertTrue('TEST-IE' in str(sys.exc_info()[1])) except ValueError: if 'lxml' in self.etree.__name__: self.assertTrue(sys.version_info[0] >= 3) self.assertTrue('TEST-VE' in str(sys.exc_info()[1])) else: self.assertTrue(False) if 'lxml' in self.etree.__name__: self.assertEqual(["start"], events) else: # cElementTree calls end() as well self.assertTrue("start" in events) def test_elementtree_parser_target(self): assertEqual = self.assertEqual assertFalse = self.assertFalse Element = self.etree.Element events = [] class Target(object): def start(self, tag, attrib): events.append("start") assertFalse(attrib) assertEqual("TAG", tag) def end(self, tag): events.append("end") assertEqual("TAG", tag) def close(self): return Element("DONE") parser = self.XMLParser(target=Target()) tree = self.etree.ElementTree() tree.parse(BytesIO(""), parser=parser) self.assertEqual("DONE", tree.getroot().tag) self.assertEqual(["start", "end"], events) def test_parser_target_attrib(self): assertEqual = self.assertEqual events = [] class Target(object): def start(self, tag, attrib): events.append("start-" + tag) for name, value in attrib.items(): assertEqual(tag + name, value) def end(self, tag): events.append("end-" + tag) def close(self): return "DONE" parser = self.XMLParser(target=Target()) parser.feed('') done = parser.close() self.assertEqual("DONE", done) self.assertEqual(["start-root", "start-sub", "end-sub", "end-root"], events) def test_parser_target_data(self): events = [] class Target(object): def start(self, tag, attrib): events.append("start-" + tag) def end(self, tag): events.append("end-" + tag) def data(self, data): events.append("data-" + data) def close(self): return "DONE" parser = self.XMLParser(target=Target()) parser.feed('AB') done = parser.close() self.assertEqual("DONE", done) self.assertEqual(["start-root", "data-A", "start-sub", "end-sub", "data-B", "end-root"], events) def test_parser_target_entity(self): events = [] class Target(object): def __init__(self): self._data = [] def _flush_data(self): if self._data: events.append("data-" + ''.join(self._data)) del self._data[:] def start(self, tag, attrib): self._flush_data() events.append("start-" + tag) def end(self, tag): self._flush_data() events.append("end-" + tag) def data(self, data): self._data.append(data) def close(self): self._flush_data() return "DONE" parser = self.XMLParser(target=Target()) dtd = ''' ]> ''' parser.feed(dtd+'this is &ent;') done = parser.close() self.assertEqual("DONE", done) self.assertEqual(["start-root", "start-sub", "end-sub", "start-sub", "data-this is an entity", "end-sub", "start-sub", "end-sub", "end-root"], events) required_versions_ET['test_parser_target_entity_unknown'] = (1,3) def test_parser_target_entity_unknown(self): events = [] class Target(object): def __init__(self): self._data = [] def _flush_data(self): if self._data: events.append("data-" + ''.join(self._data)) del self._data[:] def start(self, tag, attrib): self._flush_data() events.append("start-" + tag) def end(self, tag): self._flush_data() events.append("end-" + tag) def data(self, data): self._data.append(data) def close(self): self._flush_data() return "DONE" parser = self.XMLParser(target=Target()) def feed(): parser.feed('some &ent;') parser.close() self.assertRaises(self.etree.ParseError, feed) def test_treebuilder(self): builder = self.etree.TreeBuilder() el = builder.start("root", {'a':'A', 'b':'B'}) self.assertEqual("root", el.tag) self.assertEqual({'a':'A', 'b':'B'}, el.attrib) builder.data("ROOTTEXT") el = builder.start("child", {'x':'X', 'y':'Y'}) self.assertEqual("child", el.tag) self.assertEqual({'x':'X', 'y':'Y'}, el.attrib) builder.data("CHILDTEXT") el = builder.end("child") self.assertEqual("child", el.tag) self.assertEqual({'x':'X', 'y':'Y'}, el.attrib) self.assertEqual("CHILDTEXT", el.text) self.assertEqual(None, el.tail) builder.data("CHILDTAIL") root = builder.end("root") self.assertEqual("root", root.tag) self.assertEqual("ROOTTEXT", root.text) self.assertEqual("CHILDTEXT", root[0].text) self.assertEqual("CHILDTAIL", root[0].tail) def test_treebuilder_target(self): parser = self.XMLParser(target=self.etree.TreeBuilder()) parser.feed('ROOTTEXTCHILDTEXTCHILDTAIL') root = parser.close() self.assertEqual("root", root.tag) self.assertEqual("ROOTTEXT", root.text) self.assertEqual("CHILDTEXT", root[0].text) self.assertEqual("CHILDTAIL", root[0].tail) # helper methods def _writeElement(self, element, encoding='us-ascii'): """Write out element for comparison. """ data = self.etree.tostring(element, encoding=encoding) return canonicalize(data) def _writeElementFile(self, element, encoding='us-ascii'): """Write out element for comparison, using real file. """ ElementTree = self.etree.ElementTree handle, filename = tempfile.mkstemp() try: f = open(filename, 'wb') tree = ElementTree(element=element) tree.write(f, encoding=encoding) f.close() f = open(filename, 'rb') data = f.read() f.close() finally: os.close(handle) os.remove(filename) return canonicalize(data) def assertXML(self, expected, element, encoding='us-ascii'): """Writes element out and checks whether it is expected. Does this two ways; once using BytesIO, once using a real file. """ if isinstance(expected, unicode): expected = expected.encode(encoding) self.assertEqual(expected, self._writeElement(element, encoding)) self.assertEqual(expected, self._writeElementFile(element, encoding)) def assertEncodingDeclaration(self, result, encoding): "Checks if the result XML byte string specifies the encoding." enc_re = r"<\?xml[^>]+ encoding=[\"']([^\"']+)[\"']" if isinstance(result, str): has_encoding = re.compile(enc_re).match else: has_encoding = re.compile(_bytes(enc_re)).match self.assertTrue(has_encoding(result)) result_encoding = has_encoding(result).group(1) self.assertEqual(result_encoding.upper(), encoding.upper()) def _rootstring(self, tree): return self.etree.tostring(tree.getroot()).replace( _bytes(' '), _bytes('')).replace(_bytes('\n'), _bytes('')) def _check_element_tree(self, tree): self._check_element(tree.getroot()) def _check_element(self, element): self.assertTrue(hasattr(element, 'tag')) self.assertTrue(hasattr(element, 'attrib')) self.assertTrue(hasattr(element, 'text')) self.assertTrue(hasattr(element, 'tail')) self._check_string(element.tag) self._check_mapping(element.attrib) if element.text != None: self._check_string(element.text) if element.tail != None: self._check_string(element.tail) def _check_string(self, string): len(string) for char in string: self.assertEqual(1, len(char)) new_string = string + "" new_string = string + " " string[:0] def _check_mapping(self, mapping): len(mapping) keys = mapping.keys() values = mapping.values() items = mapping.items() for key in keys: item = mapping[key] mapping["key"] = "value" self.assertEqual("value", mapping["key"]) class _XMLPullParserTest(unittest.TestCase): etree = None def _feed(self, parser, data, chunk_size=None): if chunk_size is None: parser.feed(data) else: for i in range(0, len(data), chunk_size): parser.feed(data[i:i+chunk_size]) def _close_and_return_root(self, parser): if 'ElementTree' in self.etree.__name__: # ElementTree's API is a bit unwieldy in Py3.4 root = parser._close_and_return_root() else: root = parser.close() return root def assert_event_tags(self, parser, expected): events = parser.read_events() self.assertEqual([(action, elem.tag) for action, elem in events], expected) def test_simple_xml(self): for chunk_size in (None, 1, 5): #with self.subTest(chunk_size=chunk_size): parser = self.etree.XMLPullParser() self.assert_event_tags(parser, []) self._feed(parser, "\n", chunk_size) self.assert_event_tags(parser, []) self._feed(parser, "\n text\n", chunk_size) self.assert_event_tags(parser, [('end', 'element')]) self._feed(parser, "texttail\n", chunk_size) self._feed(parser, "\n", chunk_size) self.assert_event_tags(parser, [ ('end', 'element'), ('end', 'empty-element'), ]) self._feed(parser, "\n", chunk_size) self.assert_event_tags(parser, [('end', 'root')]) root = self._close_and_return_root(parser) self.assertEqual(root.tag, 'root') def test_feed_while_iterating(self): parser = self.etree.XMLPullParser() it = parser.read_events() self._feed(parser, "\n text\n") action, elem = next(it) self.assertEqual((action, elem.tag), ('end', 'element')) self._feed(parser, "\n") action, elem = next(it) self.assertEqual((action, elem.tag), ('end', 'root')) try: next(it) except StopIteration: self.assertTrue(True) else: self.assertTrue(False) def test_simple_xml_with_ns(self): parser = self.etree.XMLPullParser() self.assert_event_tags(parser, []) self._feed(parser, "\n") self.assert_event_tags(parser, []) self._feed(parser, "\n") self.assert_event_tags(parser, []) self._feed(parser, "text\n") self.assert_event_tags(parser, [('end', '{namespace}element')]) self._feed(parser, "texttail\n") self._feed(parser, "\n") self.assert_event_tags(parser, [ ('end', '{namespace}element'), ('end', '{namespace}empty-element'), ]) self._feed(parser, "\n") self.assert_event_tags(parser, [('end', '{namespace}root')]) root = self._close_and_return_root(parser) self.assertEqual(root.tag, '{namespace}root') def test_ns_events(self): parser = self.etree.XMLPullParser(events=('start-ns', 'end-ns')) self._feed(parser, "\n") self._feed(parser, "\n") self.assertEqual( list(parser.read_events()), [('start-ns', ('', 'namespace'))]) self._feed(parser, "text\n") self._feed(parser, "texttail\n") self._feed(parser, "\n") self._feed(parser, "\n") self.assertEqual(list(parser.read_events()), [('end-ns', None)]) parser.close() def test_events(self): parser = self.etree.XMLPullParser(events=()) self._feed(parser, "\n") self.assert_event_tags(parser, []) parser = self.etree.XMLPullParser(events=('start', 'end')) self._feed(parser, "\n") self.assert_event_tags(parser, []) self._feed(parser, "\n") self.assert_event_tags(parser, [('start', 'root')]) self._feed(parser, "text\n") self.assert_event_tags(parser, [('end', 'element')]) self._feed(parser, "texttail\n") self.assert_event_tags(parser, [ ('start', '{foo}element'), ('start', '{foo}empty-element'), ('end', '{foo}empty-element'), ('end', '{foo}element'), ]) self._feed(parser, "") root = self._close_and_return_root(parser) self.assert_event_tags(parser, [('end', 'root')]) self.assertEqual(root.tag, 'root') parser = self.etree.XMLPullParser(events=('start',)) self._feed(parser, "\n") self.assert_event_tags(parser, []) self._feed(parser, "\n") self.assert_event_tags(parser, [('start', 'root')]) self._feed(parser, "text\n") self.assert_event_tags(parser, []) self._feed(parser, "texttail\n") self.assert_event_tags(parser, [ ('start', '{foo}element'), ('start', '{foo}empty-element'), ]) self._feed(parser, "") root = self._close_and_return_root(parser) self.assertEqual(root.tag, 'root') def test_events_sequence(self): # Test that events can be some sequence that's not just a tuple or list eventset = set(['end', 'start']) parser = self.etree.XMLPullParser(events=eventset) self._feed(parser, "bar") self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')]) class DummyIter: def __init__(self): self.events = iter(['start', 'end', 'start-ns']) def __iter__(self): return self def __next__(self): return next(self.events) next = __next__ parser = self.etree.XMLPullParser(events=DummyIter()) self._feed(parser, "bar") self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')]) def test_unknown_event(self): try: self.etree.XMLPullParser(events=('start', 'end', 'bogus')) except ValueError: self.assertTrue(True) else: self.assertTrue(False) if etree: class ETreeTestCase(_ETreeTestCaseBase): etree = etree class ETreePullTestCase(_XMLPullParserTest): etree = etree if ElementTree: class ElementTreeTestCase(_ETreeTestCaseBase): etree = ElementTree @classmethod def setUpClass(cls): import warnings # ElementTree warns about getiterator() in recent Pythons warnings.filterwarnings( 'ignore', r'This method will be removed.*\.iter\(\).*instead', PendingDeprecationWarning) filter_by_version( ElementTreeTestCase, ElementTreeTestCase.required_versions_ET, ET_VERSION) if hasattr(ElementTree, 'XMLPullParser'): class ElementTreePullTestCase(_XMLPullParserTest): etree = ElementTree else: ElementTreePullTestCase = None if cElementTree: class CElementTreeTestCase(_ETreeTestCaseBase): etree = cElementTree filter_by_version( CElementTreeTestCase, CElementTreeTestCase.required_versions_cET, CET_VERSION) def test_suite(): suite = unittest.TestSuite() if etree: suite.addTests([unittest.makeSuite(ETreeTestCase)]) suite.addTests([unittest.makeSuite(ETreePullTestCase)]) if ElementTree: suite.addTests([unittest.makeSuite(ElementTreeTestCase)]) if ElementTreePullTestCase: suite.addTests([unittest.makeSuite(ElementTreePullTestCase)]) if cElementTree: suite.addTests([unittest.makeSuite(CElementTreeTestCase)]) return suite if __name__ == '__main__': print('to test use test.py %s' % __file__)