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 - def test_element_base(self):
74 el = self.etree.ElementBase() 75 self.assertEqual('ElementBase', el.tag) 76 root = self.etree.ElementBase() 77 root.append(el) 78 self.assertEqual('ElementBase', root[0].tag)
79
81 el = self.etree.ElementBase(etree.ElementBase()) 82 self.assertEqual('ElementBase', el.tag) 83 self.assertEqual(1, len(el)) 84 self.assertEqual('ElementBase', el[0].tag) 85 86 root = self.etree.ElementBase() 87 root.append(el) 88 self.assertEqual('ElementBase', root[0].tag) 89 self.assertEqual('ElementBase', root[0][0].tag)
90
91 - def test_comment_base(self):
92 el = self.etree.CommentBase('some text') 93 self.assertEqual(self.etree.Comment, el.tag) 94 self.assertEqual('some text', el.text) 95 root = self.etree.Element('root') 96 root.append(el) 97 self.assertEqual('some text', root[0].text)
98
99 - def test_pi_base(self):
100 el = self.etree.PIBase('the target', 'some text') 101 self.assertEqual(self.etree.ProcessingInstruction, el.tag) 102 self.assertEqual('some text', el.text) 103 root = self.etree.Element('root') 104 root.append(el) 105 self.assertEqual('some text', root[0].text)
106 107
108 -class ClassLookupTestCase(HelperTestCase):
109 """Test cases for different Element class lookup mechanisms. 110 """ 111 etree = etree 112
113 - def tearDown(self):
116
117 - def test_namespace_lookup(self):
118 class TestElement(etree.ElementBase): 119 FIND_ME = "namespace class"
120 121 lookup = etree.ElementNamespaceClassLookup() 122 etree.set_element_class_lookup(lookup) 123 124 ns = lookup.get_namespace("myNS") 125 ns[None] = TestElement 126 127 root = etree.XML(xml_str) 128 self.assertEqual(root.FIND_ME, 129 TestElement.FIND_ME) 130 self.assertEqual(root[0].FIND_ME, 131 TestElement.FIND_ME) 132 self.assertFalse(hasattr(root[0][-1], 'FIND_ME'))
133
134 - def test_default_class_lookup(self):
135 class TestElement(etree.ElementBase): 136 FIND_ME = "default element"
137 class TestComment(etree.CommentBase): 138 FIND_ME = "default comment" 139 class TestPI(etree.PIBase): 140 FIND_ME = "default pi" 141 142 parser = etree.XMLParser() 143 144 lookup = etree.ElementDefaultClassLookup( 145 element=TestElement, comment=TestComment, pi=TestPI) 146 parser.set_element_class_lookup(lookup) 147 148 root = etree.XML(_bytes("""<?xml version='1.0'?> 149 <root> 150 <?myPI?> 151 <!-- hi --> 152 </root> 153 """), parser) 154 155 self.assertEqual("default element", root.FIND_ME) 156 self.assertEqual("default pi", root[0].FIND_ME) 157 self.assertEqual("default comment", root[1].FIND_ME) 158
159 - def test_evil_class_lookup(self):
160 class MyLookup(etree.CustomElementClassLookup): 161 def lookup(self, t, d, ns, name): 162 if name == 'none': 163 return None 164 elif name == 'obj': 165 return object() 166 else: 167 return etree.ElementBase
168 169 parser = etree.XMLParser() 170 parser.set_element_class_lookup(MyLookup()) 171 172 root = etree.XML(_bytes('<none/>'), parser) 173 self.assertEqual('none', root.tag) 174 175 self.assertRaises( 176 TypeError, 177 etree.XML, _bytes("<obj />"), parser) 178 179 root = etree.XML(_bytes('<root/>'), parser) 180 self.assertEqual('root', root.tag) 181
182 - def test_attribute_based_lookup(self):
183 class TestElement(etree.ElementBase): 184 FIND_ME = "attribute_based"
185 186 class_dict = {"A1" : TestElement} 187 188 lookup = etree.AttributeBasedElementClassLookup( 189 "a1", class_dict) 190 etree.set_element_class_lookup(lookup) 191 192 root = etree.XML(xml_str) 193 self.assertFalse(hasattr(root, 'FIND_ME')) 194 self.assertEqual(root[0].FIND_ME, 195 TestElement.FIND_ME) 196 self.assertFalse(hasattr(root[0][0], 'FIND_ME')) 197
198 - def test_custom_lookup(self):
199 class TestElement(etree.ElementBase): 200 FIND_ME = "custom"
201 202 class MyLookup(etree.CustomElementClassLookup): 203 def lookup(self, t, d, ns, name): 204 if name == 'c1': 205 return TestElement 206 207 etree.set_element_class_lookup( MyLookup() ) 208 209 root = etree.XML(xml_str) 210 self.assertFalse(hasattr(root, 'FIND_ME')) 211 self.assertEqual(root[0].FIND_ME, 212 TestElement.FIND_ME) 213 self.assertFalse(hasattr(root[0][1], 'FIND_ME')) 214
215 - def test_custom_lookup_ns_fallback(self):
216 class TestElement1(etree.ElementBase): 217 FIND_ME = "custom"
218 219 class TestElement2(etree.ElementBase): 220 FIND_ME = "nsclasses" 221 222 class MyLookup(etree.CustomElementClassLookup): 223 def lookup(self, t, d, ns, name): 224 if name == 'c1': 225 return TestElement1 226 227 lookup = etree.ElementNamespaceClassLookup( MyLookup() ) 228 etree.set_element_class_lookup(lookup) 229 230 ns = lookup.get_namespace("otherNS") 231 ns[None] = TestElement2 232 233 root = etree.XML(xml_str) 234 self.assertFalse(hasattr(root, 'FIND_ME')) 235 self.assertEqual(root[0].FIND_ME, 236 TestElement1.FIND_ME) 237 self.assertFalse(hasattr(root[0][1], 'FIND_ME')) 238 self.assertEqual(root[0][-1].FIND_ME, 239 TestElement2.FIND_ME) 240
241 - def test_parser_based_lookup(self):
242 class TestElement(etree.ElementBase): 243 FIND_ME = "parser_based"
244 245 lookup = etree.ParserBasedElementClassLookup() 246 etree.set_element_class_lookup(lookup) 247 248 class MyLookup(etree.CustomElementClassLookup): 249 def lookup(self, t, d, ns, name): 250 return TestElement 251 252 parser = etree.XMLParser() 253 parser.set_element_class_lookup( MyLookup() ) 254 255 root = etree.parse(BytesIO(xml_str), parser).getroot() 256 self.assertEqual(root.FIND_ME, 257 TestElement.FIND_ME) 258 self.assertEqual(root[0].FIND_ME, 259 TestElement.FIND_ME) 260 261 root = etree.parse(BytesIO(xml_str)).getroot() 262 self.assertFalse(hasattr(root, 'FIND_ME')) 263 self.assertFalse(hasattr(root[0], 'FIND_ME')) 264
265 - def test_class_lookup_reentry(self):
266 XML = self.etree.XML 267 268 class TestElement(etree.ElementBase): 269 FIND_ME = "here"
270 271 root = None 272 class MyLookup(etree.CustomElementClassLookup): 273 el = None 274 def lookup(self, t, d, ns, name): 275 if root is not None: # not in the parser 276 if self.el is None and name == "a": 277 self.el = [] 278 self.el.append(root.find(name)) 279 return TestElement 280 281 parser = self.etree.XMLParser() 282 parser.set_element_class_lookup(MyLookup()) 283 284 root = XML(_bytes('<root><a>A</a><b xmlns="test">B</b></root>'), 285 parser) 286 287 a = root[0] 288 self.assertEqual(a.tag, "a") 289 self.assertEqual(root[0].tag, "a") 290 del a 291 self.assertEqual(root[0].tag, "a") 292
293 - def test_lookup_without_fallback(self):
294 class Lookup(etree.CustomElementClassLookup): 295 def __init__(self): 296 # no super call here, so no fallback is set 297 pass
298 299 def lookup(self, node_type, document, namespace, name): 300 return Foo 301 302 class Foo(etree.ElementBase): 303 def custom(self): 304 return "test" 305 306 parser = self.etree.XMLParser() 307 parser.set_element_class_lookup( Lookup() ) 308 309 root = etree.XML('<foo/>', parser) 310 311 self.assertEqual("test", root.custom()) 312 313
314 -def test_suite():
315 suite = unittest.TestSuite() 316 suite.addTests([unittest.makeSuite(ProxyTestCase)]) 317 suite.addTests([unittest.makeSuite(ClassLookupTestCase)]) 318 return suite
319 320 if __name__ == '__main__': 321 print('to test use test.py %s' % __file__) 322