# -*- coding: utf-8 -*-
"""
Tests specific to the extended etree API
Tests that apply to the general ElementTree API should go into
test_elementtree
"""
import os.path
import unittest
import copy
import sys
import re
import operator
import tempfile
import gzip
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 etree, StringIO, BytesIO, HelperTestCase, fileInTestDir, read_file
from common_imports import SillyFileLike, LargeFileLikeUnicode, doctest, make_doctest
from common_imports import canonicalize, sorted, _str, _bytes
print("")
print("TESTED VERSION: %s" % etree.__version__)
print(" Python: " + repr(sys.version_info))
print(" lxml.etree: " + repr(etree.LXML_VERSION))
print(" libxml used: " + repr(etree.LIBXML_VERSION))
print(" libxml compiled: " + repr(etree.LIBXML_COMPILED_VERSION))
print(" libxslt used: " + repr(etree.LIBXSLT_VERSION))
print(" libxslt compiled: " + repr(etree.LIBXSLT_COMPILED_VERSION))
print("")
try:
_unicode = unicode
except NameError:
# Python 3
_unicode = str
class ETreeOnlyTestCase(HelperTestCase):
"""Tests only for etree, not ElementTree"""
etree = etree
def test_version(self):
self.assert_(isinstance(etree.__version__, _unicode))
self.assert_(isinstance(etree.LXML_VERSION, tuple))
self.assertEqual(len(etree.LXML_VERSION), 4)
self.assert_(isinstance(etree.LXML_VERSION[0], int))
self.assert_(isinstance(etree.LXML_VERSION[1], int))
self.assert_(isinstance(etree.LXML_VERSION[2], int))
self.assert_(isinstance(etree.LXML_VERSION[3], int))
self.assert_(etree.__version__.startswith(
str(etree.LXML_VERSION[0])))
def test_c_api(self):
if hasattr(self.etree, '__pyx_capi__'):
# newer Pyrex compatible C-API
self.assert_(isinstance(self.etree.__pyx_capi__, dict))
self.assert_(len(self.etree.__pyx_capi__) > 0)
else:
# older C-API mechanism
self.assert_(hasattr(self.etree, '_import_c_api'))
def test_element_names(self):
Element = self.etree.Element
el = Element('name')
self.assertEquals(el.tag, 'name')
el = Element('{}name')
self.assertEquals(el.tag, 'name')
def test_element_name_empty(self):
Element = self.etree.Element
el = Element('name')
self.assertRaises(ValueError, Element, '{}')
self.assertRaises(ValueError, setattr, el, 'tag', '{}')
self.assertRaises(ValueError, Element, '{test}')
self.assertRaises(ValueError, setattr, el, 'tag', '{test}')
def test_element_name_colon(self):
Element = self.etree.Element
self.assertRaises(ValueError, Element, 'p:name')
self.assertRaises(ValueError, Element, '{test}p:name')
el = Element('name')
self.assertRaises(ValueError, setattr, el, 'tag', 'p:name')
def test_element_name_quote(self):
Element = self.etree.Element
self.assertRaises(ValueError, Element, "p'name")
self.assertRaises(ValueError, Element, 'p"name')
self.assertRaises(ValueError, Element, "{test}p'name")
self.assertRaises(ValueError, Element, '{test}p"name')
el = Element('name')
self.assertRaises(ValueError, setattr, el, 'tag', "p'name")
self.assertRaises(ValueError, setattr, el, 'tag', 'p"name')
def test_element_name_space(self):
Element = self.etree.Element
self.assertRaises(ValueError, Element, ' name ')
self.assertRaises(ValueError, Element, 'na me')
self.assertRaises(ValueError, Element, '{test} name')
el = Element('name')
self.assertRaises(ValueError, setattr, el, 'tag', ' name ')
def test_subelement_name_empty(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
el = Element('name')
self.assertRaises(ValueError, SubElement, el, '{}')
self.assertRaises(ValueError, SubElement, el, '{test}')
def test_subelement_name_colon(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
el = Element('name')
self.assertRaises(ValueError, SubElement, el, 'p:name')
self.assertRaises(ValueError, SubElement, el, '{test}p:name')
def test_subelement_name_quote(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
el = Element('name')
self.assertRaises(ValueError, SubElement, el, "p'name")
self.assertRaises(ValueError, SubElement, el, "{test}p'name")
self.assertRaises(ValueError, SubElement, el, 'p"name')
self.assertRaises(ValueError, SubElement, el, '{test}p"name')
def test_subelement_name_space(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
el = Element('name')
self.assertRaises(ValueError, SubElement, el, ' name ')
self.assertRaises(ValueError, SubElement, el, 'na me')
self.assertRaises(ValueError, SubElement, el, '{test} name')
def test_subelement_attribute_invalid(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
el = Element('name')
self.assertRaises(ValueError, SubElement, el, 'name', {'a b c' : 'abc'})
self.assertRaises(ValueError, SubElement, el, 'name', {'a' : 'a\0\n'})
self.assertEquals(0, len(el))
def test_qname_empty(self):
QName = self.etree.QName
self.assertRaises(ValueError, QName, '')
self.assertRaises(ValueError, QName, 'test', '')
def test_qname_colon(self):
QName = self.etree.QName
self.assertRaises(ValueError, QName, 'p:name')
self.assertRaises(ValueError, QName, 'test', 'p:name')
def test_qname_space(self):
QName = self.etree.QName
self.assertRaises(ValueError, QName, ' name ')
self.assertRaises(ValueError, QName, 'na me')
self.assertRaises(ValueError, QName, 'test', ' name')
def test_qname_namespace_localname(self):
# ET doesn't have namespace/localname properties on QNames
QName = self.etree.QName
namespace, localname = 'http://myns', 'a'
qname = QName(namespace, localname)
self.assertEquals(namespace, qname.namespace)
self.assertEquals(localname, qname.localname)
def test_qname_element(self):
# ET doesn't have namespace/localname properties on QNames
QName = self.etree.QName
qname1 = QName('http://myns', 'a')
a = self.etree.Element(qname1, nsmap={'p' : 'http://myns'})
qname2 = QName(a)
self.assertEquals(a.tag, qname1.text)
self.assertEquals(qname1.text, qname2.text)
self.assertEquals(qname1, qname2)
def test_qname_text_resolve(self):
# ET doesn't resove QNames as text values
etree = self.etree
qname = etree.QName('http://myns', 'a')
a = etree.Element(qname, nsmap={'p' : 'http://myns'})
a.text = qname
self.assertEquals("p:a", a.text)
def test_nsmap_prefix_invalid(self):
etree = self.etree
self.assertRaises(ValueError,
etree.Element, "root", nsmap={'"' : 'testns'})
self.assertRaises(ValueError,
etree.Element, "root", nsmap={'&' : 'testns'})
self.assertRaises(ValueError,
etree.Element, "root", nsmap={'a:b' : 'testns'})
def test_attribute_has_key(self):
# ET in Py 3.x has no "attrib.has_key()" method
XML = self.etree.XML
root = XML(_bytes(''))
self.assertEquals(
True, root.attrib.has_key('bar'))
self.assertEquals(
False, root.attrib.has_key('baz'))
self.assertEquals(
False, root.attrib.has_key('hah'))
self.assertEquals(
True,
root.attrib.has_key('{http://ns.codespeak.net/test}baz'))
def test_attribute_set(self):
Element = self.etree.Element
root = Element("root")
root.set("attr", "TEST")
self.assertEquals("TEST", root.get("attr"))
def test_attribute_set_invalid(self):
# ElementTree accepts arbitrary attribute values
# lxml.etree allows only strings
Element = self.etree.Element
root = Element("root")
self.assertRaises(TypeError, root.set, "newattr", 5)
self.assertRaises(TypeError, root.set, "newattr", None)
def test_strip_attributes(self):
XML = self.etree.XML
xml = _bytes('')
root = XML(xml)
self.etree.strip_attributes(root, 'a')
self.assertEquals(_bytes(''),
self._writeElement(root))
root = XML(xml)
self.etree.strip_attributes(root, 'b', 'c')
self.assertEquals(_bytes(''),
self._writeElement(root))
def test_strip_attributes_ns(self):
XML = self.etree.XML
xml = _bytes('')
root = XML(xml)
self.etree.strip_attributes(root, 'a')
self.assertEquals(
_bytes(''),
self._writeElement(root))
root = XML(xml)
self.etree.strip_attributes(root, '{http://test/ns}a', 'c')
self.assertEquals(
_bytes(''),
self._writeElement(root))
root = XML(xml)
self.etree.strip_attributes(root, '{http://test/ns}*')
self.assertEquals(
_bytes(''),
self._writeElement(root))
def test_strip_elements(self):
XML = self.etree.XML
xml = _bytes('')
root = XML(xml)
self.etree.strip_elements(root, 'a')
self.assertEquals(_bytes(''),
self._writeElement(root))
root = XML(xml)
self.etree.strip_elements(root, 'b', 'c', 'X', 'Y', 'Z')
self.assertEquals(_bytes(''),
self._writeElement(root))
root = XML(xml)
self.etree.strip_elements(root, 'c')
self.assertEquals(_bytes(''),
self._writeElement(root))
def test_strip_elements_ns(self):
XML = self.etree.XML
xml = _bytes('TESTABCBTATXABTCTATXT')
root = XML(xml)
self.etree.strip_elements(root, 'a')
self.assertEquals(_bytes('TESTABCBTATXXT'),
self._writeElement(root))
root = XML(xml)
self.etree.strip_elements(root, '{urn:a}b', 'c')
self.assertEquals(_bytes('TESTABCBTATXACTATXT'),
self._writeElement(root))
root = XML(xml)
self.etree.strip_elements(root, '{urn:a}*', 'c')
self.assertEquals(_bytes('TESTXACTATXT'),
self._writeElement(root))
root = XML(xml)
self.etree.strip_elements(root, '{urn:a}*', 'c', with_tail=False)
self.assertEquals(_bytes('TESTATXABTCTATXT'),
self._writeElement(root))
def test_strip_tags(self):
XML = self.etree.XML
xml = _bytes('TESTABCTBTATXABTCTATXT')
root = XML(xml)
self.etree.strip_tags(root, 'a')
self.assertEquals(_bytes('TESTABCTBTATXABTCTATXT'),
self._writeElement(root))
root = XML(xml)
self.etree.strip_tags(root, 'b', 'c', 'X', 'Y', 'Z')
self.assertEquals(_bytes('TESTABCTBTATXABTCTATXT'),
self._writeElement(root))
root = XML(xml)
self.etree.strip_tags(root, 'c')
self.assertEquals(_bytes('TESTABCTBTATXABTCTATXT'),
self._writeElement(root))
def test_strip_tags_pi_comment(self):
XML = self.etree.XML
PI = self.etree.ProcessingInstruction
Comment = self.etree.Comment
xml = _bytes('\n\nTESTXT\n\n')
root = XML(xml)
self.etree.strip_tags(root, PI)
self.assertEquals(_bytes('\n\nTESTXT\n\n'),
self._writeElement(root))
root = XML(xml)
self.etree.strip_tags(root, Comment)
self.assertEquals(_bytes('\n\nTESTXT\n\n'),
self._writeElement(root))
root = XML(xml)
self.etree.strip_tags(root, PI, Comment)
self.assertEquals(_bytes('\n\nTESTXT\n\n'),
self._writeElement(root))
root = XML(xml)
self.etree.strip_tags(root, Comment, PI)
self.assertEquals(_bytes('\n\nTESTXT\n\n'),
self._writeElement(root))
def test_strip_tags_pi_comment_all(self):
XML = self.etree.XML
ElementTree = self.etree.ElementTree
PI = self.etree.ProcessingInstruction
Comment = self.etree.Comment
xml = _bytes('\n\nTESTXT\n\n')
root = XML(xml)
self.etree.strip_tags(ElementTree(root), PI)
self.assertEquals(_bytes('\nTESTXT\n'),
self._writeElement(root))
root = XML(xml)
self.etree.strip_tags(ElementTree(root), Comment)
self.assertEquals(_bytes('\nTESTXT\n'),
self._writeElement(root))
root = XML(xml)
self.etree.strip_tags(ElementTree(root), PI, Comment)
self.assertEquals(_bytes('TESTXT'),
self._writeElement(root))
root = XML(xml)
self.etree.strip_tags(ElementTree(root), Comment, PI)
self.assertEquals(_bytes('TESTXT'),
self._writeElement(root))
def test_strip_tags_doc_style(self):
XML = self.etree.XML
xml = _bytes('''
I like
sheep.
I like lots of
sheep.
Click
here for
those sheep.
'''.strip())
root = XML(xml)
self.etree.strip_tags(root, 'a')
self.assertEquals(re.sub(_bytes('?a[^>]*>'), _bytes(''), xml).replace(_bytes('
'), _bytes('
')),
self._writeElement(root))
root = XML(xml)
self.etree.strip_tags(root, 'a', 'br')
self.assertEquals(re.sub(_bytes('?a[^>]*>'), _bytes(''),
re.sub(_bytes('
]*>'), _bytes(''), xml)),
self._writeElement(root))
def test_strip_tags_ns(self):
XML = self.etree.XML
xml = _bytes('TESTABCTBTATXABTCTATXT')
root = XML(xml)
self.etree.strip_tags(root, 'a')
self.assertEquals(_bytes('TESTABCTBTATXABTCTATXT'),
self._writeElement(root))
root = XML(xml)
self.etree.strip_tags(root, '{urn:a}b', 'c')
self.assertEquals(_bytes('TESTABCTBTATXABTCTATXT'),
self._writeElement(root))
root = XML(xml)
self.etree.strip_tags(root, '{urn:a}*', 'c')
self.assertEquals(_bytes('TESTABCTBTATXABTCTATXT'),
self._writeElement(root))
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.assertEquals(a[0].target, 'foo')
self.assertEquals(a[0].text, 'some more text')
def test_pi_parse(self):
XML = self.etree.XML
root = XML(_bytes(""))
self.assertEquals(root[0].target, "mypi")
self.assertEquals(root[0].text, "my test ")
def test_pi_pseudo_attributes_get(self):
XML = self.etree.XML
root = XML(_bytes(""))
self.assertEquals(root[0].target, "mypi")
self.assertEquals(root[0].get('my'), "1")
self.assertEquals(root[0].get('test'), " abc ")
self.assertEquals(root[0].get('quotes'), "' '")
self.assertEquals(root[0].get('only'), None)
self.assertEquals(root[0].get('names'), None)
self.assertEquals(root[0].get('nope'), None)
def test_pi_pseudo_attributes_attrib(self):
XML = self.etree.XML
root = XML(_bytes(""))
self.assertEquals(root[0].target, "mypi")
self.assertEquals(root[0].attrib['my'], "1")
self.assertEquals(root[0].attrib['test'], " abc ")
self.assertEquals(root[0].attrib['quotes'], "' '")
self.assertRaises(KeyError, root[0].attrib.__getitem__, 'only')
self.assertRaises(KeyError, root[0].attrib.__getitem__, 'names')
self.assertRaises(KeyError, root[0].attrib.__getitem__, 'nope')
def test_deepcopy_pi(self):
# previously caused a crash
ProcessingInstruction = self.etree.ProcessingInstruction
a = ProcessingInstruction("PI", "ONE")
b = copy.deepcopy(a)
b.text = "ANOTHER"
self.assertEquals('ONE', a.text)
self.assertEquals('ANOTHER', b.text)
def test_deepcopy_elementtree_pi(self):
XML = self.etree.XML
tostring = self.etree.tostring
root = XML(_bytes(""))
tree1 = self.etree.ElementTree(root)
self.assertEquals(_bytes(""),
tostring(tree1))
tree2 = copy.deepcopy(tree1)
self.assertEquals(_bytes(""),
tostring(tree2))
root2 = copy.deepcopy(tree1.getroot())
self.assertEquals(_bytes(""),
tostring(root2))
def test_deepcopy_elementtree_dtd(self):
XML = self.etree.XML
tostring = self.etree.tostring
xml = _bytes('\n]>\n')
root = XML(xml)
tree1 = self.etree.ElementTree(root)
self.assertEquals(xml, tostring(tree1))
tree2 = copy.deepcopy(tree1)
self.assertEquals(xml, tostring(tree2))
root2 = copy.deepcopy(tree1.getroot())
self.assertEquals(_bytes(""),
tostring(root2))
def test_attribute_set(self):
# ElementTree accepts arbitrary attribute values
# lxml.etree allows only strings
Element = self.etree.Element
root = Element("root")
root.set("attr", "TEST")
self.assertEquals("TEST", root.get("attr"))
self.assertRaises(TypeError, root.set, "newattr", 5)
def test_parse_remove_comments(self):
fromstring = self.etree.fromstring
tostring = self.etree.tostring
XMLParser = self.etree.XMLParser
xml = _bytes('')
parser = XMLParser(remove_comments=True)
root = fromstring(xml, parser)
self.assertEquals(
_bytes(''),
tostring(root))
def test_parse_remove_pis(self):
parse = self.etree.parse
tostring = self.etree.tostring
XMLParser = self.etree.XMLParser
xml = _bytes('')
f = BytesIO(xml)
tree = parse(f)
self.assertEquals(
xml,
tostring(tree))
parser = XMLParser(remove_pis=True)
tree = parse(f, parser)
self.assertEquals(
_bytes(''),
tostring(tree))
def test_parse_parser_type_error(self):
# ET raises IOError only
parse = self.etree.parse
self.assertRaises(TypeError, parse, 'notthere.xml', object())
def test_iterparse_tree_comments(self):
# ET removes comments
iterparse = self.etree.iterparse
tostring = self.etree.tostring
f = BytesIO('')
events = list(iterparse(f))
root = events[-1][1]
self.assertEquals(3, len(events))
self.assertEquals(
_bytes(''),
tostring(root))
def test_iterparse_comments(self):
# ET removes comments
iterparse = self.etree.iterparse
tostring = self.etree.tostring
def name(event, el):
if event == 'comment':
return el.text
else:
return el.tag
f = BytesIO('')
events = list(iterparse(f, events=('end', 'comment')))
root = events[-1][1]
self.assertEquals(6, len(events))
self.assertEquals(['A', ' B ', 'c', 'b', 'C', 'a'],
[ name(*item) for item in events ])
self.assertEquals(
_bytes(''),
tostring(root))
def test_iterparse_pis(self):
# ET removes pis
iterparse = self.etree.iterparse
tostring = self.etree.tostring
ElementTree = self.etree.ElementTree
def name(event, el):
if event == 'pi':
return (el.target, el.text)
else:
return el.tag
f = BytesIO('')
events = list(iterparse(f, events=('end', 'pi')))
root = events[-2][1]
self.assertEquals(8, len(events))
self.assertEquals([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b',
('pid','d'), 'a', ('pie','e')],
[ name(*item) for item in events ])
self.assertEquals(
_bytes(''),
tostring(ElementTree(root)))
def test_iterparse_remove_comments(self):
iterparse = self.etree.iterparse
tostring = self.etree.tostring
f = BytesIO('')
events = list(iterparse(f, remove_comments=True,
events=('end', 'comment')))
root = events[-1][1]
self.assertEquals(3, len(events))
self.assertEquals(['c', 'b', 'a'],
[ el.tag for (event, el) in events ])
self.assertEquals(
_bytes(''),
tostring(root))
def test_iterparse_broken(self):
iterparse = self.etree.iterparse
f = BytesIO('')
# ET raises ExpatError, lxml raises XMLSyntaxError
self.assertRaises(self.etree.XMLSyntaxError, list, iterparse(f))
def test_iterparse_strip(self):
iterparse = self.etree.iterparse
f = BytesIO("""
\n \n b test \n
\n\t \n \n """)
iterator = iterparse(f, remove_blank_text=True)
text = [ (element.text, element.tail)
for event, element in iterator ]
self.assertEquals(
[(" b test ", None), (" \n ", None), (None, None)],
text)
def test_iterparse_tag(self):
iterparse = self.etree.iterparse
f = BytesIO('')
iterator = iterparse(f, tag="b", events=('start', 'end'))
events = list(iterator)
root = iterator.root
self.assertEquals(
[('start', root[0]), ('end', root[0])],
events)
def test_iterparse_tag_all(self):
iterparse = self.etree.iterparse
f = BytesIO('')
iterator = iterparse(f, tag="*", events=('start', 'end'))
events = list(iterator)
self.assertEquals(
8,
len(events))
def test_iterparse_tag_ns(self):
iterparse = self.etree.iterparse
f = BytesIO('')
iterator = iterparse(f, tag="{urn:test:1}b", events=('start', 'end'))
events = list(iterator)
root = iterator.root
self.assertEquals(
[('start', root[0]), ('end', root[0])],
events)
def test_iterparse_tag_ns_empty(self):
iterparse = self.etree.iterparse
f = BytesIO('')
iterator = iterparse(f, tag="{}b", events=('start', 'end'))
events = list(iterator)
root = iterator.root
self.assertEquals(
[('start', root[0]), ('end', root[0])],
events)
f = BytesIO('')
iterator = iterparse(f, tag="{}b", events=('start', 'end'))
events = list(iterator)
root = iterator.root
self.assertEquals([], events)
def test_iterparse_tag_ns_all(self):
iterparse = self.etree.iterparse
f = BytesIO('')
iterator = iterparse(f, tag="{urn:test:1}*", events=('start', 'end'))
events = list(iterator)
self.assertEquals(8, len(events))
def test_iterparse_tag_ns_empty_all(self):
iterparse = self.etree.iterparse
f = BytesIO('')
iterator = iterparse(f, tag="{}*", events=('start', 'end'))
events = list(iterator)
self.assertEquals([], events)
f = BytesIO('')
iterator = iterparse(f, tag="{}*", events=('start', 'end'))
events = list(iterator)
self.assertEquals(8, len(events))
def test_iterparse_encoding_error(self):
text = _str('Søk på nettet')
wrong_declaration = ""
xml_latin1 = (_str('%s%s') % (wrong_declaration, text)
).encode('iso-8859-1')
self.assertRaises(self.etree.ParseError,
list, self.etree.iterparse(BytesIO(xml_latin1)))
def test_iterparse_encoding_8bit_override(self):
text = _str('Søk på nettet', encoding="UTF-8")
wrong_declaration = ""
xml_latin1 = (_str('%s%s') % (wrong_declaration, text)
).encode('iso-8859-1')
iterator = self.etree.iterparse(BytesIO(xml_latin1),
encoding="iso-8859-1")
self.assertEquals(1, len(list(iterator)))
a = iterator.root
self.assertEquals(a.text, text)
def test_iterparse_keep_cdata(self):
tostring = self.etree.tostring
f = BytesIO('')
context = self.etree.iterparse(f, strip_cdata=False)
content = [ el.text for event,el in context ]
self.assertEquals(['test'], content)
self.assertEquals(_bytes(''),
tostring(context.root))
def test_parser_encoding_unknown(self):
self.assertRaises(
LookupError, self.etree.XMLParser, encoding="hopefully unknown")
def test_parser_encoding(self):
self.etree.XMLParser(encoding="ascii")
self.etree.XMLParser(encoding="utf-8")
self.etree.XMLParser(encoding="iso-8859-1")
def test_feed_parser_recover(self):
parser = self.etree.XMLParser(recover=True)
parser.feed('<')
parser.feed('a test="works"')
parser.feed('> not closed!
parser.feed('>')
root = parser.close()
self.assertEquals(root.tag, "root")
self.assertEquals(len(root), 1)
self.assertEquals(root[0].tag, "a")
self.assertEquals(root[0].get("test"), "works")
self.assertEquals(len(root[0]), 1)
self.assertEquals(root[0][0].tag, "othertag")
# FIXME: would be nice to get some errors logged ...
#self.assert_(len(parser.error_log) > 0, "error log is empty")
def test_elementtree_parser_target_type_error(self):
assertEquals = self.assertEquals
assertFalse = self.assertFalse
events = []
class Target(object):
def start(self, tag, attrib):
events.append("start")
assertFalse(attrib)
assertEquals("TAG", tag)
def end(self, tag):
events.append("end")
assertEquals("TAG", tag)
def close(self):
return "DONE" # no Element!
parser = self.etree.XMLParser(target=Target())
tree = self.etree.ElementTree()
self.assertRaises(TypeError,
tree.parse, BytesIO(""), parser=parser)
self.assertEquals(["start", "end"], events)
def test_parser_target_feed_exception(self):
# ET doesn't call .close() on errors
events = []
class Target(object):
def start(self, tag, attrib):
events.append("start-" + tag)
def end(self, tag):
events.append("end-" + tag)
if tag == 'a':
raise ValueError("dead and gone")
def data(self, data):
events.append("data-" + data)
def close(self):
events.append("close")
return "DONE"
parser = self.etree.XMLParser(target=Target())
try:
parser.feed(_bytes('AcaB'))
done = parser.close()
self.fail("error expected, but parsing succeeded")
except ValueError:
done = 'value error received as expected'
self.assertEquals(["start-root", "data-A", "start-a",
"data-ca", "end-a", "close"],
events)
def test_parser_target_fromstring_exception(self):
# ET doesn't call .close() on errors
events = []
class Target(object):
def start(self, tag, attrib):
events.append("start-" + tag)
def end(self, tag):
events.append("end-" + tag)
if tag == 'a':
raise ValueError("dead and gone")
def data(self, data):
events.append("data-" + data)
def close(self):
events.append("close")
return "DONE"
parser = self.etree.XMLParser(target=Target())
try:
done = self.etree.fromstring(_bytes('AcaB'),
parser=parser)
self.fail("error expected, but parsing succeeded")
except ValueError:
done = 'value error received as expected'
self.assertEquals(["start-root", "data-A", "start-a",
"data-ca", "end-a", "close"],
events)
def test_parser_target_comment(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 comment(self, text):
events.append("comment-" + text)
def close(self):
return "DONE"
parser = self.etree.XMLParser(target=Target())
parser.feed(_bytes('AB'))
done = parser.close()
self.assertEquals("DONE", done)
self.assertEquals(["comment-a", "start-root", "data-A", "comment-b",
"start-sub", "end-sub", "comment-c", "data-B",
"end-root", "comment-d"],
events)
def test_parser_target_pi(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 pi(self, target, data):
events.append("pi-" + target + "-" + data)
def close(self):
return "DONE"
parser = self.etree.XMLParser(target=Target())
parser.feed(_bytes('AB'))
done = parser.close()
self.assertEquals("DONE", done)
self.assertEquals(["pi-test-a", "start-root", "data-A", "pi-test-b",
"data-B", "end-root", "pi-test-c"],
events)
def test_parser_target_cdata(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.etree.XMLParser(target=Target(),
strip_cdata=False)
parser.feed(_bytes('AB'))
done = parser.close()
self.assertEquals("DONE", done)
self.assertEquals(["start-root", "data-A", "start-a",
"data-ca", "end-a", "data-B", "end-root"],
events)
def test_parser_target_recover(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):
events.append("close")
return "DONE"
parser = self.etree.XMLParser(target=Target(),
recover=True)
parser.feed(_bytes('AcaB'))
done = parser.close()
self.assertEquals("DONE", done)
self.assertEquals(["start-root", "data-A", "start-a",
"data-ca", "end-a", "data-B",
"end-root", "close"],
events)
def test_iterwalk_tag(self):
iterwalk = self.etree.iterwalk
root = self.etree.XML(_bytes(''))
iterator = iterwalk(root, tag="b", events=('start', 'end'))
events = list(iterator)
self.assertEquals(
[('start', root[0]), ('end', root[0])],
events)
def test_iterwalk_tag_all(self):
iterwalk = self.etree.iterwalk
root = self.etree.XML(_bytes(''))
iterator = iterwalk(root, tag="*", events=('start', 'end'))
events = list(iterator)
self.assertEquals(
8,
len(events))
def test_iterwalk(self):
iterwalk = self.etree.iterwalk
root = self.etree.XML(_bytes(''))
events = list(iterwalk(root))
self.assertEquals(
[('end', root[0]), ('end', root[1]), ('end', root)],
events)
def test_iterwalk_start(self):
iterwalk = self.etree.iterwalk
root = self.etree.XML(_bytes(''))
iterator = iterwalk(root, events=('start',))
events = list(iterator)
self.assertEquals(
[('start', root), ('start', root[0]), ('start', root[1])],
events)
def test_iterwalk_start_end(self):
iterwalk = self.etree.iterwalk
root = self.etree.XML(_bytes(''))
iterator = iterwalk(root, events=('start','end'))
events = list(iterator)
self.assertEquals(
[('start', root), ('start', root[0]), ('end', root[0]),
('start', root[1]), ('end', root[1]), ('end', root)],
events)
def test_iterwalk_clear(self):
iterwalk = self.etree.iterwalk
root = self.etree.XML(_bytes(''))
iterator = iterwalk(root)
for event, elem in iterator:
elem.clear()
self.assertEquals(0,
len(root))
def test_iterwalk_attrib_ns(self):
iterwalk = self.etree.iterwalk
root = self.etree.XML(_bytes(''))
attr_name = '{testns}bla'
events = []
iterator = iterwalk(root, events=('start','end','start-ns','end-ns'))
for event, elem in iterator:
events.append(event)
if event == 'start':
if elem.tag != '{ns1}a':
elem.set(attr_name, 'value')
self.assertEquals(
['start-ns', 'start', 'start', 'start-ns', 'start',
'end', 'end-ns', 'end', 'end', 'end-ns'],
events)
self.assertEquals(
None,
root.get(attr_name))
self.assertEquals(
'value',
root[0].get(attr_name))
def test_iterwalk_getiterator(self):
iterwalk = self.etree.iterwalk
root = self.etree.XML(_bytes(''))
counts = []
for event, elem in iterwalk(root):
counts.append(len(list(elem.getiterator())))
self.assertEquals(
[1,2,1,4],
counts)
def test_resolve_string_dtd(self):
parse = self.etree.parse
parser = self.etree.XMLParser(dtd_validation=True)
assertEqual = self.assertEqual
test_url = _str("__nosuch.dtd")
class MyResolver(self.etree.Resolver):
def resolve(self, url, id, context):
assertEqual(url, test_url)
return self.resolve_string(
_str('''
''') % url, context)
parser.resolvers.add(MyResolver())
xml = _str('&myentity;') % test_url
tree = parse(StringIO(xml), parser)
root = tree.getroot()
self.assertEquals(root.text, test_url)
def test_resolve_bytes_dtd(self):
parse = self.etree.parse
parser = self.etree.XMLParser(dtd_validation=True)
assertEqual = self.assertEqual
test_url = _str("__nosuch.dtd")
class MyResolver(self.etree.Resolver):
def resolve(self, url, id, context):
assertEqual(url, test_url)
return self.resolve_string(
(_str('''
''') % url).encode('utf-8'),
context)
parser.resolvers.add(MyResolver())
xml = _str('&myentity;') % test_url
tree = parse(StringIO(xml), parser)
root = tree.getroot()
self.assertEquals(root.text, test_url)
def test_resolve_filelike_dtd(self):
parse = self.etree.parse
parser = self.etree.XMLParser(dtd_validation=True)
assertEqual = self.assertEqual
test_url = _str("__nosuch.dtd")
class MyResolver(self.etree.Resolver):
def resolve(self, url, id, context):
assertEqual(url, test_url)
return self.resolve_file(
SillyFileLike(
_str('''
''') % url), context)
parser.resolvers.add(MyResolver())
xml = _str('&myentity;') % test_url
tree = parse(StringIO(xml), parser)
root = tree.getroot()
self.assertEquals(root.text, test_url)
def test_resolve_filename_dtd(self):
parse = self.etree.parse
parser = self.etree.XMLParser(attribute_defaults=True)
assertEqual = self.assertEqual
test_url = _str("__nosuch.dtd")
class MyResolver(self.etree.Resolver):
def resolve(self, url, id, context):
assertEqual(url, test_url)
return self.resolve_filename(
fileInTestDir('test.dtd'), context)
parser.resolvers.add(MyResolver())
xml = _str('') % test_url
tree = parse(StringIO(xml), parser)
root = tree.getroot()
self.assertEquals(
root.attrib, {'default': 'valueA'})
self.assertEquals(
root[0].attrib, {'default': 'valueB'})
def test_resolve_filename_dtd_relative(self):
parse = self.etree.parse
parser = self.etree.XMLParser(attribute_defaults=True)
assertEqual = self.assertEqual
test_url = _str("__nosuch.dtd")
class MyResolver(self.etree.Resolver):
def resolve(self, url, id, context):
assertEqual(url, fileInTestDir(test_url))
return self.resolve_filename(
fileInTestDir('test.dtd'), context)
parser.resolvers.add(MyResolver())
xml = _str('') % test_url
tree = parse(StringIO(xml), parser,
base_url=fileInTestDir('__test.xml'))
root = tree.getroot()
self.assertEquals(
root.attrib, {'default': 'valueA'})
self.assertEquals(
root[0].attrib, {'default': 'valueB'})
def test_resolve_file_dtd(self):
parse = self.etree.parse
parser = self.etree.XMLParser(attribute_defaults=True)
assertEqual = self.assertEqual
test_url = _str("__nosuch.dtd")
class MyResolver(self.etree.Resolver):
def resolve(self, url, id, context):
assertEqual(url, test_url)
return self.resolve_file(
open(fileInTestDir('test.dtd'), 'rb'), context)
parser.resolvers.add(MyResolver())
xml = _str('') % test_url
tree = parse(StringIO(xml), parser)
root = tree.getroot()
self.assertEquals(
root.attrib, {'default': 'valueA'})
self.assertEquals(
root[0].attrib, {'default': 'valueB'})
def test_resolve_empty(self):
parse = self.etree.parse
parser = self.etree.XMLParser(load_dtd=True)
assertEqual = self.assertEqual
test_url = _str("__nosuch.dtd")
class check(object):
resolved = False
class MyResolver(self.etree.Resolver):
def resolve(self, url, id, context):
assertEqual(url, test_url)
check.resolved = True
return self.resolve_empty(context)
parser.resolvers.add(MyResolver())
xml = _str('&myentity;') % test_url
self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser)
self.assert_(check.resolved)
def test_resolve_error(self):
parse = self.etree.parse
parser = self.etree.XMLParser(dtd_validation=True)
class _LocalException(Exception):
pass
class MyResolver(self.etree.Resolver):
def resolve(self, url, id, context):
raise _LocalException
parser.resolvers.add(MyResolver())
xml = '&myentity;'
self.assertRaises(_LocalException, parse, BytesIO(xml), parser)
if etree.LIBXML_VERSION > (2,6,20):
def test_entity_parse(self):
parse = self.etree.parse
tostring = self.etree.tostring
parser = self.etree.XMLParser(resolve_entities=False)
Entity = self.etree.Entity
xml = _bytes('&myentity;')
tree = parse(BytesIO(xml), parser)
root = tree.getroot()
self.assertEquals(root[0].tag, Entity)
self.assertEquals(root[0].text, "&myentity;")
self.assertEquals(root[0].tail, None)
self.assertEquals(root[0].name, "myentity")
self.assertEquals(_bytes('&myentity;'),
tostring(root))
def test_entity_restructure(self):
xml = _bytes(''' ]>
''')
parser = self.etree.XMLParser(resolve_entities=False)
root = etree.fromstring(xml, parser)
self.assertEquals([ el.tag for el in root ],
['child1', 'child2', 'child3'])
root[0] = root[-1]
self.assertEquals([ el.tag for el in root ],
['child3', 'child2'])
self.assertEquals(root[0][0].text, ' ')
self.assertEquals(root[0][0].name, 'nbsp')
def test_entity_append(self):
Entity = self.etree.Entity
Element = self.etree.Element
tostring = self.etree.tostring
root = Element("root")
root.append( Entity("test") )
self.assertEquals(root[0].tag, Entity)
self.assertEquals(root[0].text, "&test;")
self.assertEquals(root[0].tail, None)
self.assertEquals(root[0].name, "test")
self.assertEquals(_bytes('&test;'),
tostring(root))
def test_entity_values(self):
Entity = self.etree.Entity
self.assertEquals(Entity("test").text, '&test;')
self.assertEquals(Entity("#17683").text, '䔓')
self.assertEquals(Entity("#x1768").text, 'ᝨ')
self.assertEquals(Entity("#x98AF").text, '颯')
def test_entity_error(self):
Entity = self.etree.Entity
self.assertRaises(ValueError, Entity, 'a b c')
self.assertRaises(ValueError, Entity, 'a,b')
self.assertRaises(ValueError, Entity, 'a\0b')
self.assertRaises(ValueError, Entity, '#abc')
self.assertRaises(ValueError, Entity, '#xxyz')
def test_cdata(self):
CDATA = self.etree.CDATA
Element = self.etree.Element
tostring = self.etree.tostring
root = Element("root")
root.text = CDATA('test')
self.assertEquals('test',
root.text)
self.assertEquals(_bytes(''),
tostring(root))
def test_cdata_type(self):
CDATA = self.etree.CDATA
Element = self.etree.Element
root = Element("root")
root.text = CDATA("test")
self.assertEquals('test', root.text)
root.text = CDATA(_str("test"))
self.assertEquals('test', root.text)
self.assertRaises(TypeError, CDATA, 1)
def test_cdata_errors(self):
CDATA = self.etree.CDATA
Element = self.etree.Element
root = Element("root")
cdata = CDATA('test')
self.assertRaises(TypeError,
setattr, root, 'tail', cdata)
self.assertRaises(TypeError,
root.set, 'attr', cdata)
self.assertRaises(TypeError,
operator.setitem, root.attrib, 'attr', cdata)
def test_cdata_parser(self):
tostring = self.etree.tostring
parser = self.etree.XMLParser(strip_cdata=False)
root = self.etree.XML(_bytes(''), parser)
self.assertEquals('test', root.text)
self.assertEquals(_bytes(''),
tostring(root))
def test_cdata_xpath(self):
tostring = self.etree.tostring
parser = self.etree.XMLParser(strip_cdata=False)
root = self.etree.XML(_bytes(''), parser)
self.assertEquals(_bytes(''),
tostring(root))
self.assertEquals(['test'], root.xpath('//text()'))
# TypeError in etree, AssertionError in ElementTree;
def test_setitem_assert(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
self.assertRaises(TypeError,
a.__setitem__, 0, 'foo')
def test_append_error(self):
Element = self.etree.Element
root = Element('root')
# raises AssertionError in ElementTree
self.assertRaises(TypeError, root.append, None)
self.assertRaises(TypeError, root.extend, [None])
self.assertRaises(TypeError, root.extend, [Element('one'), None])
self.assertEquals('one', root[0].tag)
def test_addnext(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
root = Element('root')
SubElement(root, 'a')
SubElement(root, 'b')
self.assertEquals(['a', 'b'],
[c.tag for c in root])
root[1].addnext(root[0])
self.assertEquals(['b', 'a'],
[c.tag for c in root])
def test_addprevious(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
root = Element('root')
SubElement(root, 'a')
SubElement(root, 'b')
self.assertEquals(['a', 'b'],
[c.tag for c in root])
root[0].addprevious(root[1])
self.assertEquals(['b', 'a'],
[c.tag for c in root])
def test_addnext_root(self):
Element = self.etree.Element
a = Element('a')
b = Element('b')
self.assertRaises(TypeError, a.addnext, b)
def test_addnext_root(self):
Element = self.etree.Element
a = Element('a')
b = Element('b')
self.assertRaises(TypeError, a.addnext, b)
def test_addprevious_pi(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
PI = self.etree.PI
root = Element('root')
SubElement(root, 'a')
pi = PI('TARGET', 'TEXT')
pi.tail = "TAIL"
self.assertEquals(_bytes(''),
self._writeElement(root))
root[0].addprevious(pi)
self.assertEquals(_bytes('TAIL'),
self._writeElement(root))
def test_addprevious_root_pi(self):
Element = self.etree.Element
PI = self.etree.PI
root = Element('root')
pi = PI('TARGET', 'TEXT')
pi.tail = "TAIL"
self.assertEquals(_bytes(''),
self._writeElement(root))
root.addprevious(pi)
self.assertEquals(_bytes('\n'),
self._writeElement(root))
def test_addnext_pi(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
PI = self.etree.PI
root = Element('root')
SubElement(root, 'a')
pi = PI('TARGET', 'TEXT')
pi.tail = "TAIL"
self.assertEquals(_bytes(''),
self._writeElement(root))
root[0].addnext(pi)
self.assertEquals(_bytes('TAIL'),
self._writeElement(root))
def test_addnext_root_pi(self):
Element = self.etree.Element
PI = self.etree.PI
root = Element('root')
pi = PI('TARGET', 'TEXT')
pi.tail = "TAIL"
self.assertEquals(_bytes(''),
self._writeElement(root))
root.addnext(pi)
self.assertEquals(_bytes('\n'),
self._writeElement(root))
def test_addnext_comment(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
Comment = self.etree.Comment
root = Element('root')
SubElement(root, 'a')
comment = Comment('TEXT ')
comment.tail = "TAIL"
self.assertEquals(_bytes(''),
self._writeElement(root))
root[0].addnext(comment)
self.assertEquals(_bytes('TAIL'),
self._writeElement(root))
def test_addnext_root_comment(self):
Element = self.etree.Element
Comment = self.etree.Comment
root = Element('root')
comment = Comment('TEXT ')
comment.tail = "TAIL"
self.assertEquals(_bytes(''),
self._writeElement(root))
root.addnext(comment)
self.assertEquals(_bytes('\n'),
self._writeElement(root))
def test_addprevious_comment(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
Comment = self.etree.Comment
root = Element('root')
SubElement(root, 'a')
comment = Comment('TEXT ')
comment.tail = "TAIL"
self.assertEquals(_bytes(''),
self._writeElement(root))
root[0].addprevious(comment)
self.assertEquals(_bytes('TAIL'),
self._writeElement(root))
def test_addprevious_root_comment(self):
Element = self.etree.Element
Comment = self.etree.Comment
root = Element('root')
comment = Comment('TEXT ')
comment.tail = "TAIL"
self.assertEquals(_bytes(''),
self._writeElement(root))
root.addprevious(comment)
self.assertEquals(_bytes('\n'),
self._writeElement(root))
# ET's Elements have items() and key(), but not values()
def test_attribute_values(self):
XML = self.etree.XML
root = XML(_bytes(''))
values = root.values()
values.sort()
self.assertEquals(['Alpha', 'Beta', 'Gamma'], values)
# gives error in ElementTree
def test_comment_empty(self):
Element = self.etree.Element
Comment = self.etree.Comment
a = Element('a')
a.append(Comment())
self.assertEquals(
_bytes(''),
self._writeElement(a))
# ElementTree ignores comments
def test_comment_parse_empty(self):
ElementTree = self.etree.ElementTree
tostring = self.etree.tostring
xml = _bytes('')
f = BytesIO(xml)
doc = ElementTree(file=f)
a = doc.getroot()
self.assertEquals(
'',
a[1].text)
self.assertEquals(
xml,
tostring(a))
# ElementTree ignores comments
def test_comment_no_proxy_yet(self):
ElementTree = self.etree.ElementTree
f = BytesIO('')
doc = ElementTree(file=f)
a = doc.getroot()
self.assertEquals(
' hoi ',
a[1].text)
# does not raise an exception in ElementTree
def test_comment_immutable(self):
Element = self.etree.Element
Comment = self.etree.Comment
c = Comment()
el = Element('myel')
self.assertRaises(TypeError, c.append, el)
self.assertRaises(TypeError, c.insert, 0, el)
self.assertRaises(TypeError, c.set, "myattr", "test")
# test passing 'None' to dump
def test_dump_none(self):
self.assertRaises(TypeError, self.etree.dump, None)
def test_prefix(self):
ElementTree = self.etree.ElementTree
f = BytesIO('')
doc = ElementTree(file=f)
a = doc.getroot()
self.assertEquals(
None,
a.prefix)
self.assertEquals(
'foo',
a[0].prefix)
def test_prefix_default_ns(self):
ElementTree = self.etree.ElementTree
f = BytesIO('')
doc = ElementTree(file=f)
a = doc.getroot()
self.assertEquals(
None,
a.prefix)
self.assertEquals(
None,
a[0].prefix)
def test_getparent(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
d = SubElement(b, 'd')
self.assertEquals(
None,
a.getparent())
self.assertEquals(
a,
b.getparent())
self.assertEquals(
b.getparent(),
c.getparent())
self.assertEquals(
b,
d.getparent())
def test_iterchildren(self):
XML = self.etree.XML
root = XML(_bytes('TwoHm'))
result = []
for el in root.iterchildren():
result.append(el.tag)
self.assertEquals(['one', 'two', 'three'], result)
def test_iterchildren_reversed(self):
XML = self.etree.XML
root = XML(_bytes('TwoHm'))
result = []
for el in root.iterchildren(reversed=True):
result.append(el.tag)
self.assertEquals(['three', 'two', 'one'], result)
def test_iterchildren_tag(self):
XML = self.etree.XML
root = XML(_bytes('TwoHmBla'))
result = []
for el in root.iterchildren(tag='two'):
result.append(el.text)
self.assertEquals(['Two', 'Bla'], result)
def test_iterchildren_tag_reversed(self):
XML = self.etree.XML
root = XML(_bytes('TwoHmBla'))
result = []
for el in root.iterchildren(reversed=True, tag='two'):
result.append(el.text)
self.assertEquals(['Bla', 'Two'], result)
def test_iterchildren_tag_multiple(self):
XML = self.etree.XML
root = XML(_bytes('TwoHmBla'))
result = []
for el in root.iterchildren(tag=['two', 'three']):
result.append(el.text)
self.assertEquals(['Two', 'Bla', None], result)
def test_iterchildren_tag_multiple_reversed(self):
XML = self.etree.XML
root = XML(_bytes('TwoHmBla'))
result = []
for el in root.iterchildren(reversed=True, tag=['two', 'three']):
result.append(el.text)
self.assertEquals([None, 'Bla', 'Two'], result)
def test_iterancestors(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
d = SubElement(b, 'd')
self.assertEquals(
[],
list(a.iterancestors()))
self.assertEquals(
[a],
list(b.iterancestors()))
self.assertEquals(
[a],
list(c.iterancestors()))
self.assertEquals(
[b, a],
list(d.iterancestors()))
def test_iterancestors_tag(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
d = SubElement(b, 'd')
self.assertEquals(
[a],
list(d.iterancestors(tag='a')))
self.assertEquals(
[b, a],
list(d.iterancestors(tag='*')))
def test_iterancestors_tag_multiple(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
d = SubElement(b, 'd')
self.assertEquals(
[b, a],
list(d.iterancestors(tag=('a', 'b'))))
self.assertEquals(
[],
list(d.iterancestors(tag=('w', 'x', 'y', 'z'))))
self.assertEquals(
[],
list(d.iterancestors(tag=('d', 'x'))))
self.assertEquals(
[b, a],
list(d.iterancestors(tag=('b', '*'))))
self.assertEquals(
[b],
list(d.iterancestors(tag=('b', 'c'))))
def test_iterdescendants(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.assertEquals(
[b, d, c, e],
list(a.iterdescendants()))
self.assertEquals(
[],
list(d.iterdescendants()))
def test_iterdescendants_tag(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.assertEquals(
[],
list(a.iterdescendants('a')))
a2 = SubElement(e, 'a')
self.assertEquals(
[a2],
list(a.iterdescendants('a')))
self.assertEquals(
[a2],
list(c.iterdescendants('a')))
def test_iterdescendants_tag_multiple(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.assertEquals(
[b, e],
list(a.iterdescendants(tag=('a', 'b', 'e'))))
a2 = SubElement(e, 'a')
self.assertEquals(
[b, a2],
list(a.iterdescendants(tag=('a', 'b'))))
self.assertEquals(
[],
list(c.iterdescendants(tag=('x', 'y', 'z'))))
self.assertEquals(
[b, d, c, e, a2],
list(a.iterdescendants(tag=('x', 'y', 'z', '*'))))
def test_getroottree(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
d = SubElement(b, 'd')
self.assertEquals(
a,
a.getroottree().getroot())
self.assertEquals(
a,
b.getroottree().getroot())
self.assertEquals(
a,
d.getroottree().getroot())
def test_getnext(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
self.assertEquals(
None,
a.getnext())
self.assertEquals(
c,
b.getnext())
self.assertEquals(
None,
c.getnext())
def test_getprevious(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
d = SubElement(b, 'd')
self.assertEquals(
None,
a.getprevious())
self.assertEquals(
b,
c.getprevious())
self.assertEquals(
None,
b.getprevious())
def test_itersiblings(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
d = SubElement(b, 'd')
self.assertEquals(
[],
list(a.itersiblings()))
self.assertEquals(
[c],
list(b.itersiblings()))
self.assertEquals(
[],
list(c.itersiblings()))
self.assertEquals(
[b],
list(c.itersiblings(preceding=True)))
self.assertEquals(
[],
list(b.itersiblings(preceding=True)))
def test_itersiblings_tag(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
d = SubElement(b, 'd')
self.assertEquals(
[],
list(a.itersiblings(tag='XXX')))
self.assertEquals(
[c],
list(b.itersiblings(tag='c')))
self.assertEquals(
[c],
list(b.itersiblings(tag='*')))
self.assertEquals(
[b],
list(c.itersiblings(preceding=True, tag='b')))
self.assertEquals(
[],
list(c.itersiblings(preceding=True, tag='c')))
def test_itersiblings_tag_multiple(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(a, 'e')
self.assertEquals(
[],
list(a.itersiblings(tag=('XXX', 'YYY'))))
self.assertEquals(
[c, e],
list(b.itersiblings(tag=('c', 'd', 'e'))))
self.assertEquals(
[b],
list(c.itersiblings(preceding=True, tag=('b', 'b', 'c', 'd'))))
self.assertEquals(
[c, b],
list(e.itersiblings(preceding=True, tag=('c', '*'))))
def test_parseid(self):
parseid = self.etree.parseid
XML = self.etree.XML
xml_text = _bytes('''
]>
...
...
Regular paragraph.
XML:ID paragraph.
...
''')
tree, dic = parseid(BytesIO(xml_text))
root = tree.getroot()
root2 = XML(xml_text)
self.assertEquals(self._writeElement(root),
self._writeElement(root2))
expected = {
"chapter1" : root[0],
"xmlid" : root[3],
"warn1" : root[4]
}
self.assert_("chapter1" in dic)
self.assert_("warn1" in dic)
self.assert_("xmlid" in dic)
self._checkIDDict(dic, expected)
def test_XMLDTDID(self):
XMLDTDID = self.etree.XMLDTDID
XML = self.etree.XML
xml_text = _bytes('''
]>
...
...
Regular paragraph.
XML:ID paragraph.
...
''')
root, dic = XMLDTDID(xml_text)
root2 = XML(xml_text)
self.assertEquals(self._writeElement(root),
self._writeElement(root2))
expected = {
"chapter1" : root[0],
"xmlid" : root[3],
"warn1" : root[4]
}
self.assert_("chapter1" in dic)
self.assert_("warn1" in dic)
self.assert_("xmlid" in dic)
self._checkIDDict(dic, expected)
def test_XMLDTDID_empty(self):
XMLDTDID = self.etree.XMLDTDID
XML = self.etree.XML
xml_text = _bytes('''
...
...
Regular paragraph.
...
''')
root, dic = XMLDTDID(xml_text)
root2 = XML(xml_text)
self.assertEquals(self._writeElement(root),
self._writeElement(root2))
expected = {}
self._checkIDDict(dic, expected)
def _checkIDDict(self, dic, expected):
self.assertEquals(len(dic),
len(expected))
self.assertEquals(sorted(dic.items()),
sorted(expected.items()))
if sys.version_info < (3,):
self.assertEquals(sorted(dic.iteritems()),
sorted(expected.iteritems()))
self.assertEquals(sorted(dic.keys()),
sorted(expected.keys()))
if sys.version_info < (3,):
self.assertEquals(sorted(dic.iterkeys()),
sorted(expected.iterkeys()))
if sys.version_info < (3,):
self.assertEquals(sorted(dic.values()),
sorted(expected.values()))
self.assertEquals(sorted(dic.itervalues()),
sorted(expected.itervalues()))
def test_namespaces(self):
etree = self.etree
r = {'foo': 'http://ns.infrae.com/foo'}
e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
self.assertEquals(
'foo',
e.prefix)
self.assertEquals(
_bytes(''),
self._writeElement(e))
def test_namespaces_default(self):
etree = self.etree
r = {None: 'http://ns.infrae.com/foo'}
e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
self.assertEquals(
None,
e.prefix)
self.assertEquals(
'{http://ns.infrae.com/foo}bar',
e.tag)
self.assertEquals(
_bytes(''),
self._writeElement(e))
def test_namespaces_default_and_attr(self):
etree = self.etree
r = {None: 'http://ns.infrae.com/foo',
'hoi': 'http://ns.infrae.com/hoi'}
e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
e.set('{http://ns.infrae.com/hoi}test', 'value')
self.assertEquals(
_bytes(''),
self._writeElement(e))
def test_namespaces_elementtree(self):
etree = self.etree
r = {None: 'http://ns.infrae.com/foo',
'hoi': 'http://ns.infrae.com/hoi'}
e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r)
tree = etree.ElementTree(element=e)
etree.SubElement(e, '{http://ns.infrae.com/hoi}x')
self.assertEquals(
_bytes(''),
self._writeElement(e))
def test_namespaces_default_copy_element(self):
etree = self.etree
r = {None: 'http://ns.infrae.com/foo'}
e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
e1.append(e2)
self.assertEquals(
None,
e1.prefix)
self.assertEquals(
None,
e1[0].prefix)
self.assertEquals(
'{http://ns.infrae.com/foo}bar',
e1.tag)
self.assertEquals(
'{http://ns.infrae.com/foo}bar',
e1[0].tag)
def test_namespaces_copy_element(self):
etree = self.etree
r = {None: 'http://ns.infrae.com/BAR'}
e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r)
e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
e1.append(e2)
self.assertEquals(
None,
e1.prefix)
self.assertNotEquals(
None,
e2.prefix)
self.assertEquals(
'{http://ns.infrae.com/BAR}bar',
e1.tag)
self.assertEquals(
'{http://ns.infrae.com/foo}bar',
e2.tag)
def test_namespaces_reuse_after_move(self):
ns_href = "http://a.b.c"
one = self.etree.fromstring(
_bytes('' % ns_href))
baz = one[0][0]
two = self.etree.fromstring(
_bytes('' % ns_href))
two.append(baz)
del one # make sure the source document is deallocated
self.assertEquals('{%s}baz' % ns_href, baz.tag)
self.assertEquals(
_bytes('' % ns_href),
self.etree.tostring(two))
def test_namespace_cleanup(self):
xml = _bytes('')
root = self.etree.fromstring(xml)
self.assertEquals(xml,
self.etree.tostring(root))
self.etree.cleanup_namespaces(root)
self.assertEquals(
_bytes(''),
self.etree.tostring(root))
def test_element_nsmap(self):
etree = self.etree
r = {None: 'http://ns.infrae.com/foo',
'hoi': 'http://ns.infrae.com/hoi'}
e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
self.assertEquals(
r,
e.nsmap)
def test_subelement_nsmap(self):
etree = self.etree
re = {None: 'http://ns.infrae.com/foo',
'hoi': 'http://ns.infrae.com/hoi'}
e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re)
rs = {None: 'http://ns.infrae.com/honk',
'top': 'http://ns.infrae.com/top'}
s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs)
r = re.copy()
r.update(rs)
self.assertEquals(re, e.nsmap)
self.assertEquals(r, s.nsmap)
def test_html_prefix_nsmap(self):
etree = self.etree
el = etree.HTML('aa').find('.//page-description')
self.assertEquals({'hha': None}, el.nsmap)
def test_getiterator_filter_multiple(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')
f = SubElement(c, 'f')
self.assertEquals(
[a, b],
list(a.getiterator('a', 'b')))
self.assertEquals(
[],
list(a.getiterator('x', 'y')))
self.assertEquals(
[a, f],
list(a.getiterator('f', 'a')))
self.assertEquals(
[c, e, f],
list(c.getiterator('c', '*', 'a')))
self.assertEquals(
[],
list(a.getiterator( (), () )))
def test_getiterator_filter_multiple_tuple(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')
f = SubElement(c, 'f')
self.assertEquals(
[a, b],
list(a.getiterator( ('a', 'b') )))
self.assertEquals(
[],
list(a.getiterator( ('x', 'y') )))
self.assertEquals(
[a, f],
list(a.getiterator( ('f', 'a') )))
self.assertEquals(
[c, e, f],
list(c.getiterator( ('c', '*', 'a') )))
self.assertEquals(
[],
list(a.getiterator( () )))
def test_getiterator_filter_namespace(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('{a}a')
b = SubElement(a, '{a}b')
c = SubElement(a, '{a}c')
d = SubElement(b, '{b}d')
e = SubElement(c, '{a}e')
f = SubElement(c, '{b}f')
self.assertEquals(
[a],
list(a.getiterator('{a}a')))
self.assertEquals(
[],
list(a.getiterator('{b}a')))
self.assertEquals(
[],
list(a.getiterator('a')))
self.assertEquals(
[f],
list(c.getiterator('{b}*')))
self.assertEquals(
[d, f],
list(a.getiterator('{b}*')))
def test_getiterator_filter_entities(self):
Element = self.etree.Element
Entity = self.etree.Entity
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
entity_b = Entity("TEST-b")
b.append(entity_b)
self.assertEquals(
[entity_b],
list(a.getiterator(Entity)))
entity_a = Entity("TEST-a")
a.append(entity_a)
self.assertEquals(
[entity_b, entity_a],
list(a.getiterator(Entity)))
self.assertEquals(
[entity_b],
list(b.getiterator(Entity)))
def test_getiterator_filter_element(self):
Element = self.etree.Element
Comment = self.etree.Comment
PI = self.etree.PI
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
a.append(Comment("test"))
a.append(PI("pi", "content"))
c = SubElement(a, 'c')
self.assertEquals(
[a, b, c],
list(a.getiterator(Element)))
def test_getiterator_filter_all_comment_pi(self):
# ElementTree iterates over everything here
Element = self.etree.Element
Comment = self.etree.Comment
PI = self.etree.PI
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
a.append(Comment("test"))
a.append(PI("pi", "content"))
c = SubElement(a, 'c')
self.assertEquals(
[a, b, c],
list(a.getiterator('*')))
def test_elementtree_find_qname(self):
XML = self.etree.XML
ElementTree = self.etree.ElementTree
QName = self.etree.QName
tree = ElementTree(XML(_bytes('')))
self.assertEquals(tree.find(QName("c")), tree.getroot()[2])
def test_elementtree_findall_qname(self):
XML = self.etree.XML
ElementTree = self.etree.ElementTree
QName = self.etree.QName
tree = ElementTree(XML(_bytes('')))
self.assertEquals(len(list(tree.findall(QName("c")))), 1)
def test_elementtree_findall_ns_qname(self):
XML = self.etree.XML
ElementTree = self.etree.ElementTree
QName = self.etree.QName
tree = ElementTree(XML(
_bytes('')))
self.assertEquals(len(list(tree.findall(QName("b")))), 2)
self.assertEquals(len(list(tree.findall(QName("X", "b")))), 1)
def test_findall_ns(self):
XML = self.etree.XML
root = XML(_bytes(''))
self.assertEquals(len(root.findall(".//{X}b")), 2)
self.assertEquals(len(root.findall(".//{X}*")), 2)
self.assertEquals(len(root.findall(".//b")), 3)
def test_index(self):
etree = self.etree
e = etree.Element('foo')
for i in range(10):
etree.SubElement(e, 'a%s' % i)
for i in range(10):
self.assertEquals(
i,
e.index(e[i]))
self.assertEquals(
3, e.index(e[3], 3))
self.assertRaises(
ValueError, e.index, e[3], 4)
self.assertRaises(
ValueError, e.index, e[3], 0, 2)
self.assertRaises(
ValueError, e.index, e[8], 0, -3)
self.assertRaises(
ValueError, e.index, e[8], -5, -3)
self.assertEquals(
8, e.index(e[8], 0, -1))
self.assertEquals(
8, e.index(e[8], -12, -1))
self.assertEquals(
0, e.index(e[0], -12, -1))
def test_replace(self):
etree = self.etree
e = etree.Element('foo')
for i in range(10):
el = etree.SubElement(e, 'a%s' % i)
el.text = "text%d" % i
el.tail = "tail%d" % i
child0 = e[0]
child1 = e[1]
child2 = e[2]
e.replace(e[0], e[1])
self.assertEquals(
9, len(e))
self.assertEquals(
child1, e[0])
self.assertEquals(
child1.text, "text1")
self.assertEquals(
child1.tail, "tail1")
self.assertEquals(
child0.tail, "tail0")
self.assertEquals(
child2, e[1])
e.replace(e[-1], e[0])
self.assertEquals(
child1, e[-1])
self.assertEquals(
child1.text, "text1")
self.assertEquals(
child1.tail, "tail1")
self.assertEquals(
child2, e[0])
def test_replace_new(self):
etree = self.etree
e = etree.Element('foo')
for i in range(10):
etree.SubElement(e, 'a%s' % i)
new_element = etree.Element("test")
new_element.text = "TESTTEXT"
new_element.tail = "TESTTAIL"
child1 = e[1]
e.replace(e[0], new_element)
self.assertEquals(
new_element, e[0])
self.assertEquals(
"TESTTEXT",
e[0].text)
self.assertEquals(
"TESTTAIL",
e[0].tail)
self.assertEquals(
child1, e[1])
def test_setslice_all_empty_reversed(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[::-1] = s
self.assertEquals(
[g, f, e],
list(a))
def test_setslice_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')
x = Element('x')
y = Element('y')
a[1::2] = [x, y]
self.assertEquals(
[b, x, d, y],
list(a))
def test_setslice_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')
x = Element('x')
y = Element('y')
a[1::-1] = [x, y]
self.assertEquals(
[y, x, d, e],
list(a))
def test_setslice_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')
x = Element('x')
y = Element('y')
a[::-2] = [x, y]
self.assertEquals(
[b, y, d, x],
list(a))
def test_setslice_step_overrun(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
try:
slice
except NameError:
print("slice() not found")
return
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
d = SubElement(a, 'd')
e = SubElement(a, 'e')
x = Element('x')
y = Element('y')
z = Element('z')
self.assertRaises(
ValueError,
operator.setitem, a, slice(1,None,2), [x, y, z])
self.assertEquals(
[b, c, d, e],
list(a))
def test_sourceline_XML(self):
XML = self.etree.XML
root = XML(_bytes('''
'''))
self.assertEquals(
[2, 2, 4],
[ el.sourceline for el in root.getiterator() ])
def test_sourceline_parse(self):
parse = self.etree.parse
tree = parse(fileInTestDir('include/test_xinclude.xml'))
self.assertEquals(
[1, 2, 3],
[ el.sourceline for el in tree.getiterator() ])
def test_sourceline_iterparse_end(self):
iterparse = self.etree.iterparse
lines = [ el.sourceline for (event, el) in
iterparse(fileInTestDir('include/test_xinclude.xml')) ]
self.assertEquals(
[2, 3, 1],
lines)
def test_sourceline_iterparse_start(self):
iterparse = self.etree.iterparse
lines = [ el.sourceline for (event, el) in
iterparse(fileInTestDir('include/test_xinclude.xml'),
events=("start",)) ]
self.assertEquals(
[1, 2, 3],
lines)
def test_sourceline_element(self):
Element = self.etree.Element
SubElement = self.etree.SubElement
el = Element("test")
self.assertEquals(None, el.sourceline)
child = SubElement(el, "test")
self.assertEquals(None, el.sourceline)
self.assertEquals(None, child.sourceline)
def test_XML_base_url_docinfo(self):
etree = self.etree
root = etree.XML(_bytes(""), base_url="http://no/such/url")
docinfo = root.getroottree().docinfo
self.assertEquals(docinfo.URL, "http://no/such/url")
def test_XML_set_base_url_docinfo(self):
etree = self.etree
root = etree.XML(_bytes(""), base_url="http://no/such/url")
docinfo = root.getroottree().docinfo
self.assertEquals(docinfo.URL, "http://no/such/url")
docinfo.URL = "https://secret/url"
self.assertEquals(docinfo.URL, "https://secret/url")
def test_parse_stringio_base_url(self):
etree = self.etree
tree = etree.parse(BytesIO(""), base_url="http://no/such/url")
docinfo = tree.docinfo
self.assertEquals(docinfo.URL, "http://no/such/url")
def test_parse_base_url_docinfo(self):
etree = self.etree
tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
base_url="http://no/such/url")
docinfo = tree.docinfo
self.assertEquals(docinfo.URL, "http://no/such/url")
def test_HTML_base_url_docinfo(self):
etree = self.etree
root = etree.HTML(_bytes(""), base_url="http://no/such/url")
docinfo = root.getroottree().docinfo
self.assertEquals(docinfo.URL, "http://no/such/url")
def test_docinfo_public(self):
etree = self.etree
xml_header = ''
pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype_string = '' % (pub_id, sys_id)
xml = _bytes(xml_header + doctype_string + '')
tree = etree.parse(BytesIO(xml))
docinfo = tree.docinfo
self.assertEquals(docinfo.encoding, "ascii")
self.assertEquals(docinfo.xml_version, "1.0")
self.assertEquals(docinfo.public_id, pub_id)
self.assertEquals(docinfo.system_url, sys_id)
self.assertEquals(docinfo.root_name, 'html')
self.assertEquals(docinfo.doctype, doctype_string)
def test_docinfo_system(self):
etree = self.etree
xml_header = ''
sys_id = "some.dtd"
doctype_string = '' % sys_id
xml = _bytes(xml_header + doctype_string + '')
tree = etree.parse(BytesIO(xml))
docinfo = tree.docinfo
self.assertEquals(docinfo.encoding, "UTF-8")
self.assertEquals(docinfo.xml_version, "1.0")
self.assertEquals(docinfo.public_id, None)
self.assertEquals(docinfo.system_url, sys_id)
self.assertEquals(docinfo.root_name, 'html')
self.assertEquals(docinfo.doctype, doctype_string)
def test_docinfo_empty(self):
etree = self.etree
xml = _bytes('')
tree = etree.parse(BytesIO(xml))
docinfo = tree.docinfo
self.assertEquals(docinfo.encoding, "UTF-8")
self.assertEquals(docinfo.xml_version, "1.0")
self.assertEquals(docinfo.public_id, None)
self.assertEquals(docinfo.system_url, None)
self.assertEquals(docinfo.root_name, 'html')
self.assertEquals(docinfo.doctype, '')
def test_docinfo_name_only(self):
etree = self.etree
xml = _bytes('')
tree = etree.parse(BytesIO(xml))
docinfo = tree.docinfo
self.assertEquals(docinfo.encoding, "UTF-8")
self.assertEquals(docinfo.xml_version, "1.0")
self.assertEquals(docinfo.public_id, None)
self.assertEquals(docinfo.system_url, None)
self.assertEquals(docinfo.root_name, 'root')
self.assertEquals(docinfo.doctype, '')
def test_doctype_name_only_roundtrip(self):
etree = self.etree
xml = _bytes('\n')
tree = etree.parse(BytesIO(xml))
self.assertEquals(xml, etree.tostring(tree))
def test_doctype_output_override(self):
etree = self.etree
pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype_string = _bytes('' % (pub_id, sys_id))
xml = _bytes('\n')
tree = etree.parse(BytesIO(xml))
self.assertEquals(xml.replace(_bytes(''), doctype_string),
etree.tostring(tree, doctype=doctype_string))
def test_xml_base(self):
etree = self.etree
root = etree.XML(_bytes(""), base_url="http://no/such/url")
self.assertEquals(root.base, "http://no/such/url")
self.assertEquals(
root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
root.base = "https://secret/url"
self.assertEquals(root.base, "https://secret/url")
self.assertEquals(
root.get('{http://www.w3.org/XML/1998/namespace}base'),
"https://secret/url")
def test_xml_base_attribute(self):
etree = self.etree
root = etree.XML(_bytes(""), base_url="http://no/such/url")
self.assertEquals(root.base, "http://no/such/url")
self.assertEquals(
root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
root.set('{http://www.w3.org/XML/1998/namespace}base',
"https://secret/url")
self.assertEquals(root.base, "https://secret/url")
self.assertEquals(
root.get('{http://www.w3.org/XML/1998/namespace}base'),
"https://secret/url")
def test_html_base(self):
etree = self.etree
root = etree.HTML(_bytes(""),
base_url="http://no/such/url")
self.assertEquals(root.base, "http://no/such/url")
def test_html_base_tag(self):
etree = self.etree
root = etree.HTML(_bytes(''))
self.assertEquals(root.base, "http://no/such/url")
def test_parse_fileobject_unicode(self):
# parse from a file object that returns unicode strings
f = LargeFileLikeUnicode()
tree = self.etree.parse(f)
root = tree.getroot()
self.assert_(root.tag.endswith('root'))
def test_dtd_io(self):
# check that DTDs that go in also go back out
xml = _bytes('''\
]>
test-test\
''')
tree = self.etree.parse(BytesIO(xml))
self.assertEqual(self.etree.tostring(tree).replace(_bytes(" "), _bytes("")),
xml.replace(_bytes(" "), _bytes("")))
def test_byte_zero(self):
Element = self.etree.Element
a = Element('a')
self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho')
self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho')
self.assertRaises(ValueError, Element, 'ha\0ho')
def test_unicode_byte_zero(self):
Element = self.etree.Element
a = Element('a')
self.assertRaises(ValueError, setattr, a, "text",
_str('ha\0ho'))
self.assertRaises(ValueError, setattr, a, "tail",
_str('ha\0ho'))
self.assertRaises(ValueError, Element,
_str('ha\0ho'))
def test_byte_invalid(self):
Element = self.etree.Element
a = Element('a')
self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho')
self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho')
self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho')
self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho')
self.assertRaises(ValueError, Element, 'ha\x07ho')
self.assertRaises(ValueError, Element, 'ha\x02ho')
def test_unicode_byte_invalid(self):
Element = self.etree.Element
a = Element('a')
self.assertRaises(ValueError, setattr, a, "text",
_str('ha\x07ho'))
self.assertRaises(ValueError, setattr, a, "text",
_str('ha\x02ho'))
self.assertRaises(ValueError, setattr, a, "tail",
_str('ha\x07ho'))
self.assertRaises(ValueError, setattr, a, "tail",
_str('ha\x02ho'))
self.assertRaises(ValueError, Element,
_str('ha\x07ho'))
self.assertRaises(ValueError, Element,
_str('ha\x02ho'))
def test_unicode_byte_invalid_sequence(self):
Element = self.etree.Element
a = Element('a')
self.assertRaises(ValueError, setattr, a, "text",
_str('ha\u1234\x07ho'))
self.assertRaises(ValueError, setattr, a, "text",
_str('ha\u1234\x02ho'))
self.assertRaises(ValueError, setattr, a, "tail",
_str('ha\u1234\x07ho'))
self.assertRaises(ValueError, setattr, a, "tail",
_str('ha\u1234\x02ho'))
self.assertRaises(ValueError, Element,
_str('ha\u1234\x07ho'))
self.assertRaises(ValueError, Element,
_str('ha\u1234\x02ho'))
def test_encoding_tostring_utf16(self):
# ElementTree fails to serialize this
tostring = self.etree.tostring
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
result = tostring(a, encoding='UTF-16')
self.assertEquals(_bytes(''),
canonicalize(result))
def test_tostring_none(self):
# ElementTree raises an AssertionError here
tostring = self.etree.tostring
self.assertRaises(TypeError, self.etree.tostring, None)
def test_tostring_pretty(self):
tostring = self.etree.tostring
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
result = tostring(a)
self.assertEquals(result, _bytes(""))
result = tostring(a, pretty_print=False)
self.assertEquals(result, _bytes(""))
result = tostring(a, pretty_print=True)
self.assertEquals(result, _bytes("\n \n \n\n"))
def test_tostring_with_tail(self):
tostring = self.etree.tostring
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
a.tail = "aTAIL"
b = SubElement(a, 'b')
b.tail = "bTAIL"
c = SubElement(a, 'c')
result = tostring(a)
self.assertEquals(result, _bytes("bTAILaTAIL"))
result = tostring(a, with_tail=False)
self.assertEquals(result, _bytes("bTAIL"))
result = tostring(a, with_tail=True)
self.assertEquals(result, _bytes("bTAILaTAIL"))
def test_standalone(self):
tostring = self.etree.tostring
XML = self.etree.XML
ElementTree = self.etree.ElementTree
Element = self.etree.Element
tree = Element("root").getroottree()
self.assertEquals(None, tree.docinfo.standalone)
tree = XML(_bytes("")).getroottree()
self.assertEquals(None, tree.docinfo.standalone)
tree = XML(_bytes(
"\n"
)).getroottree()
self.assertEquals(True, tree.docinfo.standalone)
tree = XML(_bytes(
"\n"
)).getroottree()
self.assertEquals(False, tree.docinfo.standalone)
def test_tostring_standalone(self):
tostring = self.etree.tostring
XML = self.etree.XML
ElementTree = self.etree.ElementTree
root = XML(_bytes(""))
tree = ElementTree(root)
self.assertEquals(None, tree.docinfo.standalone)
result = tostring(root, xml_declaration=True, encoding="ASCII")
self.assertEquals(result, _bytes(
"\n"))
result = tostring(root, xml_declaration=True, encoding="ASCII",
standalone=True)
self.assertEquals(result, _bytes(
"\n"))
tree = ElementTree(XML(result))
self.assertEquals(True, tree.docinfo.standalone)
result = tostring(root, xml_declaration=True, encoding="ASCII",
standalone=False)
self.assertEquals(result, _bytes(
"\n"))
tree = ElementTree(XML(result))
self.assertEquals(False, tree.docinfo.standalone)
def test_tostring_standalone_in_out(self):
tostring = self.etree.tostring
XML = self.etree.XML
ElementTree = self.etree.ElementTree
root = XML(_bytes(
"\n"))
tree = ElementTree(root)
self.assertEquals(True, tree.docinfo.standalone)
result = tostring(root, xml_declaration=True, encoding="ASCII")
self.assertEquals(result, _bytes(
"\n"))
result = tostring(root, xml_declaration=True, encoding="ASCII",
standalone=True)
self.assertEquals(result, _bytes(
"\n"))
def test_tostring_method_text_encoding(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 = _str("Søk på nettet")
c = SubElement(a, 'c')
c.text = "C"
result = tostring(a, method="text", encoding="UTF-16")
self.assertEquals(_str('ABSøk på nettetCtail').encode("UTF-16"),
result)
def test_tostring_method_text_unicode(self):
tostring = self.etree.tostring
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
a.text = _str('Søk på nettetA')
a.tail = "tail"
b = SubElement(a, 'b')
b.text = "B"
b.tail = _str('Søk på nettetB')
c = SubElement(a, 'c')
c.text = "C"
self.assertRaises(UnicodeEncodeError,
tostring, a, method="text")
self.assertEquals(
_str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'),
tostring(a, encoding="UTF-8", method="text"))
def test_tounicode(self):
tounicode = self.etree.tounicode
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
self.assert_(isinstance(tounicode(a), _unicode))
self.assertEquals(_bytes(''),
canonicalize(tounicode(a)))
def test_tounicode_element(self):
tounicode = self.etree.tounicode
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
d = SubElement(c, 'd')
self.assert_(isinstance(tounicode(b), _unicode))
self.assert_(isinstance(tounicode(c), _unicode))
self.assertEquals(_bytes(''),
canonicalize(tounicode(b)))
self.assertEquals(_bytes(''),
canonicalize(tounicode(c)))
def test_tounicode_none(self):
tounicode = self.etree.tounicode
self.assertRaises(TypeError, self.etree.tounicode, None)
def test_tounicode_element_tail(self):
tounicode = self.etree.tounicode
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.assert_(isinstance(tounicode(b), _unicode))
self.assert_(tounicode(b) == 'Foo' or
tounicode(b) == 'Foo')
def test_tounicode_pretty(self):
tounicode = self.etree.tounicode
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
result = tounicode(a)
self.assertEquals(result, "")
result = tounicode(a, pretty_print=False)
self.assertEquals(result, "")
result = tounicode(a, pretty_print=True)
self.assertEquals(result, "\n \n \n\n")
def test_tostring_unicode(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.assert_(isinstance(tostring(a, encoding=_unicode), _unicode))
self.assertEquals(_bytes(''),
canonicalize(tostring(a, encoding=_unicode)))
def test_tostring_unicode_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.assert_(isinstance(tostring(b, encoding=_unicode), _unicode))
self.assert_(isinstance(tostring(c, encoding=_unicode), _unicode))
self.assertEquals(_bytes(''),
canonicalize(tostring(b, encoding=_unicode)))
self.assertEquals(_bytes(''),
canonicalize(tostring(c, encoding=_unicode)))
def test_tostring_unicode_none(self):
tostring = self.etree.tostring
self.assertRaises(TypeError, self.etree.tostring,
None, encoding=_unicode)
def test_tostring_unicode_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.assert_(isinstance(tostring(b, encoding=_unicode), _unicode))
self.assert_(tostring(b, encoding=_unicode) == 'Foo' or
tostring(b, encoding=_unicode) == 'Foo')
def test_tostring_unicode_pretty(self):
tostring = self.etree.tostring
Element = self.etree.Element
SubElement = self.etree.SubElement
a = Element('a')
b = SubElement(a, 'b')
c = SubElement(a, 'c')
result = tostring(a, encoding=_unicode)
self.assertEquals(result, "")
result = tostring(a, encoding=_unicode, pretty_print=False)
self.assertEquals(result, "")
result = tostring(a, encoding=_unicode, pretty_print=True)
self.assertEquals(result, "\n \n \n\n")
# helper methods
def _writeElement(self, element, encoding='us-ascii', compression=0):
"""Write out element for comparison.
"""
ElementTree = self.etree.ElementTree
f = BytesIO()
tree = ElementTree(element=element)
tree.write(f, encoding=encoding, compression=compression)
data = f.getvalue()
if compression:
data = zlib.decompress(data)
return canonicalize(data)
class _XIncludeTestCase(HelperTestCase):
def test_xinclude_text(self):
filename = fileInTestDir('test_broken.xml')
root = etree.XML(_bytes('''\
''' % filename))
old_text = root.text
content = read_file(filename)
old_tail = root[0].tail
self.include( etree.ElementTree(root) )
self.assertEquals(old_text + content + old_tail,
root.text)
def test_xinclude(self):
tree = etree.parse(fileInTestDir('include/test_xinclude.xml'))
self.assertNotEquals(
'a',
tree.getroot()[1].tag)
# process xincludes
self.include( tree )
# check whether we find it replaced with included data
self.assertEquals(
'a',
tree.getroot()[1].tag)
def test_xinclude_resolver(self):
class res(etree.Resolver):
include_text = read_file(fileInTestDir('test.xml'))
called = {}
def resolve(self, url, id, context):
if url.endswith(".dtd"):
self.called["dtd"] = True
return self.resolve_filename(
fileInTestDir('test.dtd'), context)
elif url.endswith("test_xinclude.xml"):
self.called["input"] = True
return None # delegate to default resolver
else:
self.called["include"] = True
return self.resolve_string(self.include_text, context)
res_instance = res()
parser = etree.XMLParser(load_dtd = True)
parser.resolvers.add(res_instance)
tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
parser = parser)
self.include(tree)
called = list(res_instance.called.items())
called.sort()
self.assertEquals(
[("dtd", True), ("include", True), ("input", True)],
called)
class ETreeXIncludeTestCase(_XIncludeTestCase):
def include(self, tree):
tree.xinclude()
class ElementIncludeTestCase(_XIncludeTestCase):
from lxml import ElementInclude
def include(self, tree):
self.ElementInclude.include(tree.getroot())
class ETreeC14NTestCase(HelperTestCase):
def test_c14n(self):
tree = self.parse(_bytes(''))
f = BytesIO()
tree.write_c14n(f)
s = f.getvalue()
self.assertEquals(_bytes(''),
s)
def test_c14n_gzip(self):
tree = self.parse(_bytes(''+''*200+''))
f = BytesIO()
tree.write_c14n(f, compression=9)
gzfile = gzip.GzipFile(fileobj=BytesIO(f.getvalue()))
try:
s = gzfile.read()
finally:
gzfile.close()
self.assertEquals(_bytes(''+''*200+''),
s)
def test_c14n_file(self):
tree = self.parse(_bytes(''))
handle, filename = tempfile.mkstemp()
try:
tree.write_c14n(filename)
data = read_file(filename, 'rb')
finally:
os.close(handle)
os.remove(filename)
self.assertEquals(_bytes(''),
data)
def test_c14n_file_gzip(self):
tree = self.parse(_bytes(''+''*200+''))
handle, filename = tempfile.mkstemp()
try:
tree.write_c14n(filename, compression=9)
f = gzip.open(filename, 'rb')
try:
data = f.read()
finally:
f.close()
finally:
os.close(handle)
os.remove(filename)
self.assertEquals(_bytes(''+''*200+''),
data)
def test_c14n_with_comments(self):
tree = self.parse(_bytes(''))
f = BytesIO()
tree.write_c14n(f)
s = f.getvalue()
self.assertEquals(_bytes('\n\n'),
s)
f = BytesIO()
tree.write_c14n(f, with_comments=True)
s = f.getvalue()
self.assertEquals(_bytes('\n\n'),
s)
f = BytesIO()
tree.write_c14n(f, with_comments=False)
s = f.getvalue()
self.assertEquals(_bytes(''),
s)
def test_c14n_tostring_with_comments(self):
tree = self.parse(_bytes(''))
s = etree.tostring(tree, method='c14n')
self.assertEquals(_bytes('\n\n'),
s)
s = etree.tostring(tree, method='c14n', with_comments=True)
self.assertEquals(_bytes('\n\n'),
s)
s = etree.tostring(tree, method='c14n', with_comments=False)
self.assertEquals(_bytes(''),
s)
def test_c14n_element_tostring_with_comments(self):
tree = self.parse(_bytes(''))
s = etree.tostring(tree.getroot(), method='c14n')
self.assertEquals(_bytes(''),
s)
s = etree.tostring(tree.getroot(), method='c14n', with_comments=True)
self.assertEquals(_bytes(''),
s)
s = etree.tostring(tree.getroot(), method='c14n', with_comments=False)
self.assertEquals(_bytes(''),
s)
def test_c14n_exclusive(self):
tree = self.parse(_bytes(
''))
f = BytesIO()
tree.write_c14n(f)
s = f.getvalue()
self.assertEquals(_bytes(''),
s)
f = BytesIO()
tree.write_c14n(f, exclusive=False)
s = f.getvalue()
self.assertEquals(_bytes(''),
s)
f = BytesIO()
tree.write_c14n(f, exclusive=True)
s = f.getvalue()
self.assertEquals(_bytes(''),
s)
def test_c14n_tostring_exclusive(self):
tree = self.parse(_bytes(
''))
s = etree.tostring(tree, method='c14n')
self.assertEquals(_bytes(''),
s)
s = etree.tostring(tree, method='c14n', exclusive=False)
self.assertEquals(_bytes(''),
s)
s = etree.tostring(tree, method='c14n', exclusive=True)
self.assertEquals(_bytes(''),
s)
def test_c14n_element_tostring_exclusive(self):
tree = self.parse(_bytes(
''))
s = etree.tostring(tree.getroot(), method='c14n')
self.assertEquals(_bytes(''),
s)
s = etree.tostring(tree.getroot(), method='c14n', exclusive=False)
self.assertEquals(_bytes(''),
s)
s = etree.tostring(tree.getroot(), method='c14n', exclusive=True)
self.assertEquals(_bytes(''),
s)
s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=False)
self.assertEquals(_bytes(''),
s)
s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True)
self.assertEquals(_bytes(''),
s)
class ETreeWriteTestCase(HelperTestCase):
def test_write(self):
tree = self.parse(_bytes(''))
f = BytesIO()
tree.write(f)
s = f.getvalue()
self.assertEquals(_bytes(''),
s)
def test_write_gzip(self):
tree = self.parse(_bytes(''+''*200+''))
f = BytesIO()
tree.write(f, compression=9)
gzfile = gzip.GzipFile(fileobj=BytesIO(f.getvalue()))
try:
s = gzfile.read()
finally:
gzfile.close()
self.assertEquals(_bytes(''+''*200+''),
s)
def test_write_gzip_level(self):
tree = self.parse(_bytes(''+''*200+''))
f = BytesIO()
tree.write(f, compression=0)
s0 = f.getvalue()
f = BytesIO()
tree.write(f)
self.assertEquals(f.getvalue(), s0)
f = BytesIO()
tree.write(f, compression=1)
s = f.getvalue()
self.assert_(len(s) <= len(s0))
gzfile = gzip.GzipFile(fileobj=BytesIO(s))
try:
s1 = gzfile.read()
finally:
gzfile.close()
f = BytesIO()
tree.write(f, compression=9)
s = f.getvalue()
self.assert_(len(s) <= len(s0))
gzfile = gzip.GzipFile(fileobj=BytesIO(s))
try:
s9 = gzfile.read()
finally:
gzfile.close()
self.assertEquals(_bytes(''+''*200+''),
s0)
self.assertEquals(_bytes(''+''*200+''),
s1)
self.assertEquals(_bytes(''+''*200+''),
s9)
def test_write_file(self):
tree = self.parse(_bytes(''))
handle, filename = tempfile.mkstemp()
try:
tree.write(filename)
data = read_file(filename, 'rb')
finally:
os.close(handle)
os.remove(filename)
self.assertEquals(_bytes(''),
data)
def test_write_file_gzip(self):
tree = self.parse(_bytes(''+''*200+''))
handle, filename = tempfile.mkstemp()
try:
tree.write(filename, compression=9)
f = gzip.open(filename, 'rb')
try:
data = f.read()
finally:
f.close()
finally:
os.close(handle)
os.remove(filename)
self.assertEquals(_bytes(''+''*200+''),
data)
def test_write_file_gzip_parse(self):
tree = self.parse(_bytes(''+''*200+''))
handle, filename = tempfile.mkstemp()
try:
tree.write(filename, compression=9)
data = etree.tostring(etree.parse(filename))
finally:
os.close(handle)
os.remove(filename)
self.assertEquals(_bytes(''+''*200+''),
data)
def test_write_file_gzipfile_parse(self):
tree = self.parse(_bytes(''+''*200+''))
handle, filename = tempfile.mkstemp()
try:
tree.write(filename, compression=9)
data = etree.tostring(etree.parse(
gzip.GzipFile(filename)))
finally:
os.close(handle)
os.remove(filename)
self.assertEquals(_bytes(''+''*200+''),
data)
class ETreeErrorLogTest(HelperTestCase):
etree = etree
def test_parse_error_logging(self):
parse = self.etree.parse
f = BytesIO('')
self.etree.clear_error_log()
try:
parse(f)
logs = None
except SyntaxError:
e = sys.exc_info()[1]
logs = e.error_log
f.close()
self.assert_([ log for log in logs
if 'mismatch' in log.message ])
self.assert_([ log for log in logs
if 'PARSER' in log.domain_name])
self.assert_([ log for log in logs
if 'ERR_TAG_NAME_MISMATCH' in log.type_name ])
self.assert_([ log for log in logs
if 1 == log.line ])
self.assert_([ log for log in logs
if 15 == log.column ])
def _test_python_error_logging(self):
"""This can't really be tested as long as there isn't a way to
reset the logging setup ...
"""
parse = self.etree.parse
messages = []
class Logger(self.etree.PyErrorLog):
def log(self, entry, message, *args):
messages.append(message)
self.etree.use_global_python_log(Logger())
f = BytesIO('')
try:
parse(f)
except SyntaxError:
pass
f.close()
self.assert_([ message for message in messages
if 'mismatch' in message ])
self.assert_([ message for message in messages
if ':PARSER:' in message])
self.assert_([ message for message in messages
if ':ERR_TAG_NAME_MISMATCH:' in message ])
self.assert_([ message for message in messages
if ':1:15:' in message ])
def test_suite():
suite = unittest.TestSuite()
suite.addTests([unittest.makeSuite(ETreeOnlyTestCase)])
suite.addTests([unittest.makeSuite(ETreeXIncludeTestCase)])
suite.addTests([unittest.makeSuite(ElementIncludeTestCase)])
suite.addTests([unittest.makeSuite(ETreeC14NTestCase)])
suite.addTests([unittest.makeSuite(ETreeWriteTestCase)])
suite.addTests([unittest.makeSuite(ETreeErrorLogTest)])
suite.addTests(
[make_doctest('../../../doc/tutorial.txt')])
suite.addTests(
[make_doctest('../../../doc/api.txt')])
suite.addTests(
[make_doctest('../../../doc/FAQ.txt')])
suite.addTests(
[make_doctest('../../../doc/parsing.txt')])
suite.addTests(
[make_doctest('../../../doc/resolvers.txt')])
return suite
if __name__ == '__main__':
print('to test use test.py %s' % __file__)