# -*- coding: utf-8 -*-
"""
Tests specific to the Python based class lookup.
"""
import unittest, os.path, sys
this_dir = os.path.dirname(__file__)
if this_dir not in sys.path:
sys.path.insert(0, this_dir) # needed for Py3
from common_imports import etree, StringIO, HelperTestCase, fileInTestDir
from common_imports import SillyFileLike, canonicalize, doctest, _bytes
from lxml.etree import PythonElementClassLookup
xml_str = _bytes('''\
0
1
2
3
3
''')
class PyClassLookupTestCase(HelperTestCase):
"""Test cases for the lxml.pyclasslookup class lookup mechanism.
"""
etree = etree
parser = etree.XMLParser()
Element = parser.makeelement
def tearDown(self):
self.parser.set_element_class_lookup(None)
super(PyClassLookupTestCase, self).tearDown()
def _setClassLookup(self, lookup_function):
class Lookup(PythonElementClassLookup):
def lookup(self, *args):
return lookup_function(*args)
self.parser.set_element_class_lookup( Lookup() )
def _buildElementClass(self):
class LocalElement(etree.ElementBase):
pass
return LocalElement
def XML(self, xml):
return self.etree.XML(xml, self.parser)
# --- Test cases
def test_lookup(self):
el_class = self._buildElementClass()
el_class.i = 1
def lookup(*args):
if el_class.i == 1:
el_class.i = 2
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertEqual(2, el_class.i)
def test_lookup_keep_ref_assertion(self):
el_class = self._buildElementClass()
el_class.EL = None
def lookup(doc, el):
if el_class.EL is None:
el_class.EL = el
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertNotEqual(None, el_class.EL)
self.assertRaises(ReferenceError, el_class.EL.getchildren)
def test_lookup_tag(self):
el_class = self._buildElementClass()
el_class.TAG = None
def lookup(doc, el):
if el_class.TAG is None:
el_class.TAG = el.tag
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertNotEqual(None, root.TAG)
self.assertEqual(root.tag, root.TAG)
def test_lookup_text(self):
el_class = self._buildElementClass()
el_class.TEXT = None
def lookup(doc, el):
if el_class.TEXT is None:
el_class.TEXT = el.text
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertNotEqual(None, root.TEXT)
self.assertEqual(root.text, root.TEXT)
def test_lookup_tail(self):
el_class = self._buildElementClass()
el_class.TAIL = None
def lookup(doc, el):
if el_class.TAIL is None:
el_class.TAIL = el.tail
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertEqual(root.tail, root.TAIL)
def test_lookup_attrib(self):
el_class = self._buildElementClass()
el_class.ATTRIB = None
def lookup(doc, el):
if el_class.ATTRIB is None:
el_class.ATTRIB = el[0].attrib
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
items1 = list(root[0].attrib.items())
items1.sort()
items2 = list(root.ATTRIB.items())
items2.sort()
self.assertEqual(items1, items2)
def test_lookup_prefix(self):
el_class = self._buildElementClass()
el_class.PREFIX = None
def lookup(doc, el):
if el_class.PREFIX is None:
el_class.PREFIX = el.prefix
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertEqual(root.prefix, root.PREFIX)
def test_lookup_sourceline(self):
el_class = self._buildElementClass()
el_class.LINE = None
def lookup(doc, el):
if el_class.LINE is None:
el_class.LINE = el.sourceline
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertEqual(root.sourceline, root.LINE)
def test_lookup_getitem(self):
el_class = self._buildElementClass()
el_class.CHILD_TAG = None
def lookup(doc, el):
el_class.CHILD_TAG = el[0].tag
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
child_tag = root.CHILD_TAG
self.assertNotEqual(None, child_tag)
self.assertEqual(root[0].tag, child_tag)
def test_lookup_getitem_neg(self):
el_class = self._buildElementClass()
el_class.CHILD_TAG = None
def lookup(doc, el):
if el_class.CHILD_TAG is None:
el_class.CHILD_TAG = el[-1].tag
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
child_tag = root.CHILD_TAG
self.assertNotEqual(None, child_tag)
self.assertEqual(root[-1].tag, child_tag)
def test_lookup_getslice(self):
el_class = self._buildElementClass()
el_class.CHILD_TAGS = None
def lookup(doc, el):
if el_class.CHILD_TAGS is None:
el_class.CHILD_TAGS = [ c.tag for c in el[1:-1] ]
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
child_tags = root.CHILD_TAGS
self.assertNotEqual(None, child_tags)
self.assertEqual([ c.tag for c in root[1:-1] ],
child_tags)
def test_lookup_len(self):
el_class = self._buildElementClass()
el_class.LEN = None
def lookup(doc, el):
if el_class.LEN is None:
el_class.LEN = len(el)
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertEqual(1, el_class.LEN)
def test_lookup_bool(self):
el_class = self._buildElementClass()
el_class.TRUE = None
def lookup(doc, el):
if el_class.TRUE is None:
el_class.TRUE = bool(el)
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertTrue(el_class.TRUE)
def test_lookup_get(self):
el_class = self._buildElementClass()
el_class.VAL = None
def lookup(doc, el):
if el_class.VAL is None:
el_class.VAL = el[0].get('a1')
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertNotEqual(None, el_class.VAL)
self.assertEqual(root[0].get('a1'), el_class.VAL)
def test_lookup_get_default(self):
el_class = self._buildElementClass()
default = str(id(el_class))
el_class.VAL = None
def lookup(doc, el):
if el_class.VAL is None:
el_class.VAL = el[0].get('unknownattribute', default)
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertEqual(default, el_class.VAL)
def test_lookup_getchildren(self):
el_class = self._buildElementClass()
el_class.CHILD_TAGS = None
def lookup(doc, el):
if el_class.CHILD_TAGS is None:
el_class.CHILD_TAGS = [ c.tag for c in el.getchildren() ]
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
child_tags = root.CHILD_TAGS
self.assertNotEqual(None, child_tags)
self.assertEqual([ c.tag for c in root.getchildren() ],
child_tags)
def test_lookup_iter_children(self):
el_class = self._buildElementClass()
el_class.CHILD_TAGS = None
def lookup(doc, el):
if el_class.CHILD_TAGS is None:
el_class.CHILD_TAGS = [ c.tag for c in el ]
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
child_tags = root.CHILD_TAGS
self.assertNotEqual(None, child_tags)
self.assertEqual([ c.tag for c in root.getchildren() ],
child_tags)
def test_lookup_iterchildren(self):
el_class = self._buildElementClass()
el_class.CHILD_TAGS = None
def lookup(doc, el):
if el_class.CHILD_TAGS is None:
el_class.CHILD_TAGS = [ c.tag for c in el.iterchildren() ]
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
child_tags = root.CHILD_TAGS
self.assertNotEqual(None, child_tags)
self.assertEqual([ c.tag for c in root.getchildren() ],
child_tags)
def test_lookup_iterchildren_tag(self):
el_class = self._buildElementClass()
el_class.CHILD_TAGS = None
def lookup(doc, el):
if not el_class.CHILD_TAGS:
el_class.CHILD_TAGS = [
c.tag for c in el.iterchildren(tag='{objectified}c2') ]
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
child_tags = root.CHILD_TAGS
self.assertNotEqual(None, child_tags)
self.assertEqual([], child_tags)
c1 = root[0]
child_tags = root.CHILD_TAGS
self.assertNotEqual(None, child_tags)
self.assertNotEqual([], child_tags)
self.assertEqual(
[ c.tag for c in root[0].iterchildren(tag='{objectified}c2') ],
child_tags)
def test_lookup_getparent(self):
el_class = self._buildElementClass()
el_class.PARENT = None
def lookup(doc, el):
if el_class.PARENT is None:
el_class.PARENT = el[0].getparent().tag
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertEqual(root.tag, root.PARENT)
def test_lookup_getnext(self):
el_class = self._buildElementClass()
el_class.NEXT = None
def lookup(doc, el):
if el_class.NEXT is None:
el_class.NEXT = el[0][1].getnext().tag
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertNotEqual(None, el_class.NEXT)
self.assertEqual(root[0][1].getnext().tag, el_class.NEXT)
def test_lookup_getprevious(self):
el_class = self._buildElementClass()
el_class.PREV = None
def lookup(doc, el):
if el_class.PREV is None:
el_class.PREV = el[0][1].getprevious().tag
return el_class
self._setClassLookup(lookup)
root = self.XML(xml_str)
self.assertNotEqual(None, el_class.PREV)
self.assertEqual(root[0][1].getprevious().tag, el_class.PREV)
def test_comments_fallback(self):
def return_none(*args):
return None
self._setClassLookup(return_none)
el = self.XML('')
self.assertEqual(el[0].tag, self.etree.Comment)
self.assertEqual(el[0].text, " hello world ")
def test_suite():
suite = unittest.TestSuite()
suite.addTests([unittest.makeSuite(PyClassLookupTestCase)])
return suite
if __name__ == '__main__':
print('to test use test.py %s' % __file__)