1
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)
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
28 """Basic tests for element proxy behaviour.
29 """
30 etree = etree
31
36
43
53
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
79
90
98
106
107
133
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
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
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
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
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
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
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:
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
294 class Lookup(etree.CustomElementClassLookup):
295 def __init__(self):
296
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
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