Package lxml :: Package tests :: Module test_classlookup
[hide private]
[frames] | no frames]

Source Code for Module lxml.tests.test_classlookup

  1  # -*- coding: utf-8 -*- 
  2   
  3  """ 
  4  Tests for different Element class lookup mechanisms. 
  5  """ 
  6   
  7   
  8  import unittest, os.path, sys, gc 
  9   
 10  this_dir = os.path.dirname(__file__) 
 11  if this_dir not in sys.path: 
 12      sys.path.insert(0, this_dir) # needed for Py3 
 13   
 14  from common_imports import etree, HelperTestCase, SillyFileLike, fileInTestDir 
 15  from common_imports import canonicalize, _bytes, _str, BytesIO, StringIO 
 16   
 17  xml_str = _bytes('''\ 
 18  <root xmlns="myNS" xmlns:other="otherNS"> 
 19    <c1 a1="A1" a2="A2" other:a3="A3"> 
 20      <c2 a1="C2">0</c2> 
 21      <c2>1</c2> 
 22      <other:c2>2</other:c2> 
 23    </c1> 
 24  </root>''') 
 25   
 26   
27 -class ProxyTestCase(HelperTestCase):
28 """Basic tests for element proxy behaviour. 29 """ 30 etree = etree 31
32 - def test_proxy_reuse(self):
33 root = etree.XML('<a><b><c/></b></a>') 34 b = root.find('b') 35 self.assertTrue(b is root[0])
36
38 root = etree.XML('<a><b><c/></b></a>') 39 b = root.find('b') 40 self.assertTrue(self.etree.iselement(b)) 41 gc.collect() 42 self.assertTrue(b is root[0])
43
45 root = etree.XML('<a><b><c/></b></a>') 46 b = root.find('b') 47 self.assertTrue(self.etree.iselement(b)) 48 c = b.find('c') 49 self.assertTrue(self.etree.iselement(c)) 50 del root 51 gc.collect() 52 self.assertTrue(b[0] is c)
53
54 - def test_proxy_hashing(self):
55 root = etree.XML('<a><b><c/></b></a>') 56 old_elements = set(root.iter()) 57 elements = root.iter() 58 del root 59 gc.collect() 60 61 missing = len(old_elements) 62 self.assertEqual(3, missing) 63 for new in elements: 64 for old in old_elements: 65 if old == new: 66 self.assertTrue(old is new) 67 missing -= 1 68 break 69 else: 70 self.assertTrue(False, "element '%s' is missing" % new.tag) 71 self.assertEqual(0, missing)
72 73
74 -class ClassLookupTestCase(HelperTestCase):
75 """Test cases for different Element class lookup mechanisms. 76 """ 77 etree = etree 78
79 - def tearDown(self):
82
83 - def test_namespace_lookup(self):
84 class TestElement(etree.ElementBase): 85 FIND_ME = "namespace class"
86 87 lookup = etree.ElementNamespaceClassLookup() 88 etree.set_element_class_lookup(lookup) 89 90 ns = lookup.get_namespace("myNS") 91 ns[None] = TestElement 92 93 root = etree.XML(xml_str) 94 self.assertEqual(root.FIND_ME, 95 TestElement.FIND_ME) 96 self.assertEqual(root[0].FIND_ME, 97 TestElement.FIND_ME) 98 self.assertFalse(hasattr(root[0][-1], 'FIND_ME'))
99
100 - def test_default_class_lookup(self):
101 class TestElement(etree.ElementBase): 102 FIND_ME = "default element"
103 class TestComment(etree.CommentBase): 104 FIND_ME = "default comment" 105 class TestPI(etree.PIBase): 106 FIND_ME = "default pi" 107 108 parser = etree.XMLParser() 109 110 lookup = etree.ElementDefaultClassLookup( 111 element=TestElement, comment=TestComment, pi=TestPI) 112 parser.set_element_class_lookup(lookup) 113 114 root = etree.XML(_bytes("""<?xml version='1.0'?> 115 <root> 116 <?myPI?> 117 <!-- hi --> 118 </root> 119 """), parser) 120 121 self.assertEqual("default element", root.FIND_ME) 122 self.assertEqual("default pi", root[0].FIND_ME) 123 self.assertEqual("default comment", root[1].FIND_ME) 124
125 - def test_attribute_based_lookup(self):
126 class TestElement(etree.ElementBase): 127 FIND_ME = "attribute_based"
128 129 class_dict = {"A1" : TestElement} 130 131 lookup = etree.AttributeBasedElementClassLookup( 132 "a1", class_dict) 133 etree.set_element_class_lookup(lookup) 134 135 root = etree.XML(xml_str) 136 self.assertFalse(hasattr(root, 'FIND_ME')) 137 self.assertEqual(root[0].FIND_ME, 138 TestElement.FIND_ME) 139 self.assertFalse(hasattr(root[0][0], 'FIND_ME')) 140
141 - def test_custom_lookup(self):
142 class TestElement(etree.ElementBase): 143 FIND_ME = "custom"
144 145 class MyLookup(etree.CustomElementClassLookup): 146 def lookup(self, t, d, ns, name): 147 if name == 'c1': 148 return TestElement 149 150 etree.set_element_class_lookup( MyLookup() ) 151 152 root = etree.XML(xml_str) 153 self.assertFalse(hasattr(root, 'FIND_ME')) 154 self.assertEqual(root[0].FIND_ME, 155 TestElement.FIND_ME) 156 self.assertFalse(hasattr(root[0][1], 'FIND_ME')) 157
158 - def test_custom_lookup_ns_fallback(self):
159 class TestElement1(etree.ElementBase): 160 FIND_ME = "custom"
161 162 class TestElement2(etree.ElementBase): 163 FIND_ME = "nsclasses" 164 165 class MyLookup(etree.CustomElementClassLookup): 166 def lookup(self, t, d, ns, name): 167 if name == 'c1': 168 return TestElement1 169 170 lookup = etree.ElementNamespaceClassLookup( MyLookup() ) 171 etree.set_element_class_lookup(lookup) 172 173 ns = lookup.get_namespace("otherNS") 174 ns[None] = TestElement2 175 176 root = etree.XML(xml_str) 177 self.assertFalse(hasattr(root, 'FIND_ME')) 178 self.assertEqual(root[0].FIND_ME, 179 TestElement1.FIND_ME) 180 self.assertFalse(hasattr(root[0][1], 'FIND_ME')) 181 self.assertEqual(root[0][-1].FIND_ME, 182 TestElement2.FIND_ME) 183
184 - def test_parser_based_lookup(self):
185 class TestElement(etree.ElementBase): 186 FIND_ME = "parser_based"
187 188 lookup = etree.ParserBasedElementClassLookup() 189 etree.set_element_class_lookup(lookup) 190 191 class MyLookup(etree.CustomElementClassLookup): 192 def lookup(self, t, d, ns, name): 193 return TestElement 194 195 parser = etree.XMLParser() 196 parser.set_element_class_lookup( MyLookup() ) 197 198 root = etree.parse(BytesIO(xml_str), parser).getroot() 199 self.assertEqual(root.FIND_ME, 200 TestElement.FIND_ME) 201 self.assertEqual(root[0].FIND_ME, 202 TestElement.FIND_ME) 203 204 root = etree.parse(BytesIO(xml_str)).getroot() 205 self.assertFalse(hasattr(root, 'FIND_ME')) 206 self.assertFalse(hasattr(root[0], 'FIND_ME')) 207
208 - def test_class_lookup_reentry(self):
209 XML = self.etree.XML 210 211 class TestElement(etree.ElementBase): 212 FIND_ME = "here"
213 214 root = None 215 class MyLookup(etree.CustomElementClassLookup): 216 el = None 217 def lookup(self, t, d, ns, name): 218 if root is not None: # not in the parser 219 if self.el is None and name == "a": 220 self.el = [] 221 self.el.append(root.find(name)) 222 return TestElement 223 224 parser = self.etree.XMLParser() 225 parser.set_element_class_lookup(MyLookup()) 226 227 root = XML(_bytes('<root><a>A</a><b xmlns="test">B</b></root>'), 228 parser) 229 230 a = root[0] 231 self.assertEqual(a.tag, "a") 232 self.assertEqual(root[0].tag, "a") 233 del a 234 self.assertEqual(root[0].tag, "a") 235
236 - def test_lookup_without_fallback(self):
237 class Lookup(etree.CustomElementClassLookup): 238 def __init__(self): 239 # no super call here, so no fallback is set 240 pass
241 242 def lookup(self, node_type, document, namespace, name): 243 return Foo 244 245 class Foo(etree.ElementBase): 246 def custom(self): 247 return "test" 248 249 parser = self.etree.XMLParser() 250 parser.set_element_class_lookup( Lookup() ) 251 252 root = etree.XML('<foo/>', parser) 253 254 self.assertEqual("test", root.custom()) 255 256
257 -def test_suite():
258 suite = unittest.TestSuite() 259 suite.addTests([unittest.makeSuite(ClassLookupTestCase)]) 260 return suite
261 262 if __name__ == '__main__': 263 print('to test use test.py %s' % __file__) 264