# -*- coding: utf-8 -*-
"""
Tests specific to the extended etree API
Tests that apply to the general ElementTree API should go into
test_elementtree
"""
from __future__ import absolute_import
from collections import OrderedDict
import os.path
import unittest
import copy
import sys
import re
import gc
import operator
import textwrap
import zlib
import gzip
from .common_imports import etree, StringIO, BytesIO, HelperTestCase
from .common_imports import fileInTestDir, fileUrlInTestDir, read_file, path2url, tmpfile
from .common_imports import SillyFileLike, LargeFileLikeUnicode, doctest, make_doctest
from .common_imports import canonicalize, _str, _bytes
print("""
TESTED VERSION: %s""" % etree.__version__ + """
Python: %r""" % (sys.version_info,) + """
lxml.etree: %r""" % (etree.LXML_VERSION,) + """
libxml used: %r""" % (etree.LIBXML_VERSION,) + """
libxml compiled: %r""" % (etree.LIBXML_COMPILED_VERSION,) + """
libxslt used: %r""" % (etree.LIBXSLT_VERSION,) + """
libxslt compiled: %r""" % (etree.LIBXSLT_COMPILED_VERSION,) + """
FS encoding: %s""" % (sys.getfilesystemencoding(),) + """
Default encoding: %s""" % (sys.getdefaultencoding(),) + """
Max Unicode: %s""" % (sys.maxunicode,) + """
""")
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.assertTrue(isinstance(etree.__version__, _unicode))
self.assertTrue(isinstance(etree.LXML_VERSION, tuple))
self.assertEqual(len(etree.LXML_VERSION), 4)
self.assertTrue(isinstance(etree.LXML_VERSION[0], int))
self.assertTrue(isinstance(etree.LXML_VERSION[1], int))
self.assertTrue(isinstance(etree.LXML_VERSION[2], int))
self.assertTrue(isinstance(etree.LXML_VERSION[3], int))
self.assertTrue(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.assertTrue(isinstance(self.etree.__pyx_capi__, dict))
self.assertTrue(len(self.etree.__pyx_capi__) > 0)
else:
# older C-API mechanism
self.assertTrue(hasattr(self.etree, '_import_c_api'))
def test_include_paths(self):
import lxml
includes = lxml.get_include()
self.assertTrue(includes)
self.assertTrue(len(includes) >= 2)
self.assertTrue(os.path.join(os.path.dirname(lxml.__file__), 'includes') in includes,
includes)
def test_element_names(self):
Element = self.etree.Element
el = Element('name')
self.assertEqual(el.tag, 'name')
el = Element('{}name')
self.assertEqual(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.assertEqual(0, len(el))
def test_qname_empty(self):
QName = self.etree.QName
self.assertRaises(ValueError, QName, '')
self.assertRaises(ValueError, QName, None)
self.assertRaises(ValueError, QName, None, None)
self.assertRaises(ValueError, QName, 'test', '')
def test_qname_none(self):
QName = self.etree.QName
q = QName(None, 'TAG')
self.assertEqual('TAG', q)
self.assertEqual('TAG', q.localname)
self.assertEqual(None, q.namespace)
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.assertEqual(namespace, qname.namespace)
self.assertEqual(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.assertEqual(a.tag, qname1.text)
self.assertEqual(a.tag, qname1)
self.assertEqual(qname1.text, qname2.text)
self.assertEqual(qname1, qname2.text)
self.assertEqual(qname1.text, qname2)
self.assertEqual(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.assertEqual("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_clear_keep_tail(self):
XML = self.etree.XML
tostring = self.etree.tostring
a = XML('B1B2
boo
boo
boo
boo
...
Regular paragraph.
XML:ID paragraph.
...
...
Regular paragraph.
XML:ID paragraph.
...
...
Regular paragraph.
...
...
Regular paragraph.
XML:ID paragraph.
...
' + '\n' * 65536 + '
\n' + 'par
\ntext
\tpar
\n' b'text
\n' b'\n'
b'
\n'
b'
pre
post
text
") ET.indent(elem) self.assertEqual( ET.tostring(elem), b'\n' b' \n' b'pre
post
text
\n' b' \n' b'' ) def test_indent_space(self): ET = self.etree elem = ET.XML("pre
post
text
") ET.indent(elem, space='\t') self.assertEqual( ET.tostring(elem), b'\n' b'\t\n' b'\t\tpre
post
text
\n' b'\t\n' b'' ) elem = ET.XML("pre
post
text
") ET.indent(elem, space='') self.assertEqual( ET.tostring(elem), b'\n' b'\n' b'pre
post
text
\n' b'\n' b'' ) def test_indent_space_caching(self): ET = self.etree elem = ET.XML("par
text
pre
post
text
") try: ET.indent(elem, level=-1) except ValueError: pass else: self.assertTrue(False, "ValueError not raised") self.assertEqual( ET.tostring(elem), b"pre
post
text
" ) ET.indent(elem, level=2) self.assertEqual( ET.tostring(elem), b'\n' b' \n' b'pre
post
text
\n' b' \n' b' ' ) elem = ET.XML("pre
post
text
") ET.indent(elem, level=1, space=' ') self.assertEqual( ET.tostring(elem), b'\n' b' \n' b'pre
post
text
\n' b' \n' b' ' ) 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.assertTrue(root.tag.endswith('root')) def test_dtd_io(self): # check that DTDs that go in also go back out xml = _bytes('''\ ]>Some text\r\n
Some text\r\n
Some text\r\n
Some text\r\n
The following is the source code of Recursive2.xml:
The following is the source code of Recursive3.xml:
The following is the source code of Recursive1.xml:
The following is multiple times the source code of NonRecursive3.xml:
The following is multiple times the source code of Leaf.xml:
One more time the source code of NonRecursive3.xml:
The following is multiple times the source code of NonRecursive3.xml:
The following is multiple times the source code of Leaf.xml:
No further includes