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
73
99
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
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
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
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
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
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:
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
237 class Lookup(etree.CustomElementClassLookup):
238 def __init__(self):
239
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
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