comparison genshi/tests/path.py @ 902:09cc3627654c experimental-inline

Sync `experimental/inline` branch with [source:trunk@1126].
author cmlenz
date Fri, 23 Apr 2010 21:08:26 +0000
parents 1837f39efd6f
children
comparison
equal deleted inserted replaced
830:de82830f8816 902:09cc3627654c
23 def __init__(self, strategy): 23 def __init__(self, strategy):
24 self.strategy = strategy 24 self.strategy = strategy
25 def test(self, ignore_context = False): 25 def test(self, ignore_context = False):
26 return self.strategy.test(ignore_context) 26 return self.strategy.test(ignore_context)
27 27
28
28 class PathTestCase(unittest.TestCase): 29 class PathTestCase(unittest.TestCase):
29 30
30 strategies = [GenericStrategy, SingleStepStrategy, SimplePathStrategy] 31 strategies = [GenericStrategy, SingleStepStrategy, SimplePathStrategy]
31 def _create_path(self, expression, expected):
32 return path
33
34 def _test_strategies(self, stream, path, render,
35 namespaces=None, variables=None):
36 for strategy in self.strategies:
37 if not strategy.supports(path):
38 continue
39 s = strategy(path)
40 rendered = FakePath(s).select(stream,namespaces=namespaces,
41 variables=variables).render()
42 msg = "Bad render using %s strategy"%str(strategy)
43 msg += "\nExpected:\t'%s'"%render
44 msg += "\nRendered:\t'%s'"%rendered
45 self.assertEqual(render, rendered, msg)
46
47 def _test_expression(self, text, expected, stream=None, render="",
48 namespaces=None, variables=None):
49 path = Path(text)
50 if expected is not None:
51 self.assertEqual(expected, repr(path))
52
53 if stream is None:
54 return
55
56 rendered = path.select(stream, namespaces=namespaces,
57 variables=variables).render()
58 msg = "Bad render using whole path"
59 msg += "\nExpected:\t'%s'"%render
60 msg += "\nRendered:\t'%s'"%rendered
61 self.assertEqual(render, rendered, msg)
62
63 if len(path.paths) == 1:
64 self._test_strategies(stream, path.paths[0], render,
65 namespaces=namespaces, variables=variables)
66
67 32
68 def test_error_no_absolute_path(self): 33 def test_error_no_absolute_path(self):
69 self.assertRaises(PathSyntaxError, Path, '/root') 34 self.assertRaises(PathSyntaxError, Path, '/root')
70 35
71 def test_error_unsupported_axis(self): 36 def test_error_unsupported_axis(self):
72 self.assertRaises(PathSyntaxError, Path, '..') 37 self.assertRaises(PathSyntaxError, Path, '..')
73 self.assertRaises(PathSyntaxError, Path, 'parent::ma') 38 self.assertRaises(PathSyntaxError, Path, 'parent::ma')
74 39
75 def test_1step(self): 40 def test_1step(self):
76 xml = XML('<root><elem/></root>') 41 xml = XML('<root><elem/></root>')
77 42 self._test_eval(
78 self._test_expression( 'elem', 43 path = 'elem',
79 '<Path "child::elem">', 44 equiv = '<Path "child::elem">',
80 xml, 45 input = xml,
81 '<elem/>') 46 output = '<elem/>'
82 47 )
83 self._test_expression( 'elem', 48 self._test_eval(
84 '<Path "child::elem">', 49 path = 'elem',
85 xml, 50 equiv = '<Path "child::elem">',
86 '<elem/>') 51 input = xml,
87 52 output = '<elem/>'
88 self._test_expression( 'child::elem', 53 )
89 '<Path "child::elem">', 54 self._test_eval(
90 xml, 55 path = 'child::elem',
91 '<elem/>') 56 equiv = '<Path "child::elem">',
92 57 input = xml,
93 self._test_expression( '//elem', 58 output = '<elem/>'
94 '<Path "descendant-or-self::elem">', 59 )
95 xml, 60 self._test_eval(
96 '<elem/>') 61 path = '//elem',
97 62 equiv = '<Path "descendant-or-self::elem">',
98 self._test_expression( 'descendant::elem', 63 input = xml,
99 '<Path "descendant::elem">', 64 output = '<elem/>'
100 xml, 65 )
101 '<elem/>') 66 self._test_eval(
67 path = 'descendant::elem',
68 equiv = '<Path "descendant::elem">',
69 input = xml,
70 output = '<elem/>'
71 )
102 72
103 def test_1step_self(self): 73 def test_1step_self(self):
104 xml = XML('<root><elem/></root>') 74 xml = XML('<root><elem/></root>')
105 75 self._test_eval(
106 self._test_expression( '.', 76 path = '.',
107 '<Path "self::node()">', 77 equiv = '<Path "self::node()">',
108 xml, 78 input = xml,
109 '<root><elem/></root>') 79 output = '<root><elem/></root>'
110 80 )
111 self._test_expression( 'self::node()', 81 self._test_eval(
112 '<Path "self::node()">', 82 path = 'self::node()',
113 xml, 83 equiv = '<Path "self::node()">',
114 '<root><elem/></root>') 84 input = xml,
85 output = '<root><elem/></root>'
86 )
115 87
116 def test_1step_wildcard(self): 88 def test_1step_wildcard(self):
117 xml = XML('<root><elem/></root>') 89 xml = XML('<root><elem/></root>')
118 90 self._test_eval(
119 self._test_expression( '*', 91 path = '*',
120 '<Path "child::*">', 92 equiv = '<Path "child::*">',
121 xml, 93 input = xml,
122 '<elem/>') 94 output = '<elem/>'
123 95 )
124 self._test_expression( 'child::*', 96 self._test_eval(
125 '<Path "child::*">', 97 path = 'child::*',
126 xml, 98 equiv = '<Path "child::*">',
127 '<elem/>') 99 input = xml,
128 100 output = '<elem/>'
129 self._test_expression( 'child::node()', 101 )
130 '<Path "child::node()">', 102 self._test_eval(
131 xml, 103 path = 'child::node()',
132 '<elem/>') 104 equiv = '<Path "child::node()">',
133 105 input = xml,
134 self._test_expression( '//*', 106 output = '<elem/>'
135 '<Path "descendant-or-self::*">', 107 )
136 xml, 108 self._test_eval(
137 '<root><elem/></root>') 109 path = '//*',
110 equiv = '<Path "descendant-or-self::*">',
111 input = xml,
112 output = '<root><elem/></root>'
113 )
138 114
139 def test_1step_attribute(self): 115 def test_1step_attribute(self):
140 self._test_expression( '@foo', 116 self._test_eval(
141 '<Path "attribute::foo">', 117 path = '@foo',
142 XML('<root/>'), 118 equiv = '<Path "attribute::foo">',
143 '') 119 input = XML('<root/>'),
144 120 output = ''
121 )
145 xml = XML('<root foo="bar"/>') 122 xml = XML('<root foo="bar"/>')
146 123 self._test_eval(
147 self._test_expression( '@foo', 124 path = '@foo',
148 '<Path "attribute::foo">', 125 equiv = '<Path "attribute::foo">',
149 xml, 126 input = xml,
150 'bar') 127 output = 'bar'
151 128 )
152 self._test_expression( './@foo', 129 self._test_eval(
153 '<Path "self::node()/attribute::foo">', 130 path = './@foo',
154 xml, 131 equiv = '<Path "self::node()/attribute::foo">',
155 'bar') 132 input = xml,
133 output = 'bar'
134 )
156 135
157 def test_1step_text(self): 136 def test_1step_text(self):
158 xml = XML('<root>Hey</root>') 137 xml = XML('<root>Hey</root>')
159 138 self._test_eval(
160 self._test_expression( 'text()', 139 path = 'text()',
161 '<Path "child::text()">', 140 equiv = '<Path "child::text()">',
162 xml, 141 input = xml,
163 'Hey') 142 output = 'Hey'
164 143 )
165 self._test_expression( './text()', 144 self._test_eval(
166 '<Path "self::node()/child::text()">', 145 path = './text()',
167 xml, 146 equiv = '<Path "self::node()/child::text()">',
168 'Hey') 147 input = xml,
169 148 output = 'Hey'
170 self._test_expression( '//text()', 149 )
171 '<Path "descendant-or-self::text()">', 150 self._test_eval(
172 xml, 151 path = '//text()',
173 'Hey') 152 equiv = '<Path "descendant-or-self::text()">',
174 153 input = xml,
175 self._test_expression( './/text()', 154 output = 'Hey'
176 '<Path "self::node()/descendant-or-self::node()/child::text()">', 155 )
177 xml, 156 self._test_eval(
178 'Hey') 157 path = './/text()',
158 equiv = '<Path "self::node()/descendant-or-self::node()/child::text()">',
159 input = xml,
160 output = 'Hey'
161 )
179 162
180 def test_2step(self): 163 def test_2step(self):
181 xml = XML('<root><foo/><bar/></root>') 164 xml = XML('<root><foo/><bar/></root>')
182 self._test_expression('*', None, xml, '<foo/><bar/>') 165 self._test_eval('*', input=xml, output='<foo/><bar/>')
183 self._test_expression('bar', None, xml, '<bar/>') 166 self._test_eval('bar', input=xml, output='<bar/>')
184 self._test_expression('baz', None, xml, '') 167 self._test_eval('baz', input=xml, output='')
185 168
186 def test_2step_attribute(self): 169 def test_2step_attribute(self):
187 xml = XML('<elem class="x"><span id="joe">Hey Joe</span></elem>') 170 xml = XML('<elem class="x"><span id="joe">Hey Joe</span></elem>')
188 self._test_expression('@*', None, xml, 'x') 171 self._test_eval('@*', input=xml, output='x')
189 self._test_expression('./@*', None, xml, 'x') 172 self._test_eval('./@*', input=xml, output='x')
190 self._test_expression('.//@*', None, xml, 'xjoe') 173 self._test_eval('.//@*', input=xml, output='xjoe')
191 self._test_expression('*/@*', None, xml, 'joe') 174 self._test_eval('*/@*', input=xml, output='joe')
192 175
193 xml = XML('<elem><foo id="1"/><foo id="2"/></elem>') 176 xml = XML('<elem><foo id="1"/><foo id="2"/></elem>')
194 self._test_expression('@*', None, xml, '') 177 self._test_eval('@*', input=xml, output='')
195 self._test_expression('foo/@*', None, xml, '12') 178 self._test_eval('foo/@*', input=xml, output='12')
196 179
197 def test_2step_complex(self): 180 def test_2step_complex(self):
198 xml = XML('<root><foo><bar/></foo></root>') 181 xml = XML('<root><foo><bar/></foo></root>')
199 182 self._test_eval(
200 self._test_expression( 'foo/bar', 183 path = 'foo/bar',
201 '<Path "child::foo/child::bar">', 184 equiv = '<Path "child::foo/child::bar">',
202 xml, 185 input = xml,
203 '<bar/>') 186 output = '<bar/>'
204 187 )
205 self._test_expression( './bar', 188 self._test_eval(
206 '<Path "self::node()/child::bar">', 189 path = './bar',
207 xml, 190 equiv = '<Path "self::node()/child::bar">',
208 '') 191 input = xml,
209 192 output = ''
210 self._test_expression( 'foo/*', 193 )
211 '<Path "child::foo/child::*">', 194 self._test_eval(
212 xml, 195 path = 'foo/*',
213 '<bar/>') 196 equiv = '<Path "child::foo/child::*">',
214 197 input = xml,
198 output = '<bar/>'
199 )
215 xml = XML('<root><foo><bar id="1"/></foo><bar id="2"/></root>') 200 xml = XML('<root><foo><bar id="1"/></foo><bar id="2"/></root>')
216 self._test_expression( './bar', 201 self._test_eval(
217 '<Path "self::node()/child::bar">', 202 path = './bar',
218 xml, 203 equiv = '<Path "self::node()/child::bar">',
219 '<bar id="2"/>') 204 input = xml,
205 output = '<bar id="2"/>'
206 )
207 xml = XML('''<table>
208 <tr><td>1</td><td>One</td></tr>
209 <tr><td>2</td><td>Two</td></tr>
210 </table>''')
211 self._test_eval(
212 path = 'tr/td[1]',
213 input = xml,
214 output = '<td>1</td><td>2</td>'
215 )
216 xml = XML('''<ul>
217 <li>item1
218 <ul><li>subitem11</li></ul>
219 </li>
220 <li>item2
221 <ul><li>subitem21</li></ul>
222 </li>
223 </ul>''')
224 self._test_eval(
225 path = 'li[2]/ul',
226 input = xml,
227 output = '<ul><li>subitem21</li></ul>'
228 )
220 229
221 def test_2step_text(self): 230 def test_2step_text(self):
222 xml = XML('<root><item>Foo</item></root>') 231 xml = XML('<root><item>Foo</item></root>')
223 232 self._test_eval(
224 self._test_expression( 'item/text()', 233 path = 'item/text()',
225 '<Path "child::item/child::text()">', 234 equiv = '<Path "child::item/child::text()">',
226 xml, 235 input = xml,
227 'Foo') 236 output = 'Foo'
228 237 )
229 self._test_expression( '*/text()', 238 self._test_eval(
230 '<Path "child::*/child::text()">', 239 path = '*/text()',
231 xml, 240 equiv = '<Path "child::*/child::text()">',
232 'Foo') 241 input = xml,
233 242 output = 'Foo'
234 self._test_expression( '//text()', 243 )
235 '<Path "descendant-or-self::text()">', 244 self._test_eval(
236 xml, 245 path = '//text()',
237 'Foo') 246 equiv = '<Path "descendant-or-self::text()">',
238 247 input = xml,
239 self._test_expression( './text()', 248 output = 'Foo'
240 '<Path "self::node()/child::text()">', 249 )
241 xml, 250 self._test_eval(
242 '') 251 path = './text()',
243 252 equiv = '<Path "self::node()/child::text()">',
253 input = xml,
254 output = ''
255 )
244 xml = XML('<root><item>Foo</item><item>Bar</item></root>') 256 xml = XML('<root><item>Foo</item><item>Bar</item></root>')
245 self._test_expression( 'item/text()', 257 self._test_eval(
246 '<Path "child::item/child::text()">', 258 path = 'item/text()',
247 xml, 259 equiv = '<Path "child::item/child::text()">',
248 'FooBar') 260 input = xml,
261 output = 'FooBar'
262 )
263 xml = XML('<root><item><name>Foo</name><sub><name>Bar</name></sub></item></root>')
264 self._test_eval(
265 path = 'item/name/text()',
266 equiv = '<Path "child::item/child::name/child::text()">',
267 input = xml,
268 output = 'Foo'
269 )
249 270
250 def test_3step(self): 271 def test_3step(self):
251 xml = XML('<root><foo><bar/></foo></root>') 272 xml = XML('<root><foo><bar/></foo></root>')
252 self._test_expression( 'foo/*', 273 self._test_eval(
253 '<Path "child::foo/child::*">', 274 path = 'foo/*',
254 xml, 275 equiv = '<Path "child::foo/child::*">',
255 '<bar/>') 276 input = xml,
277 output = '<bar/>'
278 )
256 279
257 def test_3step_complex(self): 280 def test_3step_complex(self):
258 xml = XML('<root><foo><bar/></foo></root>') 281 self._test_eval(
259 self._test_expression( '*/bar', 282 path = '*/bar',
260 '<Path "child::*/child::bar">', 283 equiv = '<Path "child::*/child::bar">',
261 xml, 284 input = XML('<root><foo><bar/></foo></root>'),
262 '<bar/>') 285 output = '<bar/>'
263 286 )
264 xml = XML('<root><foo><bar id="1"/></foo><bar id="2"/></root>') 287 self._test_eval(
265 self._test_expression( '//bar', 288 path = '//bar',
266 '<Path "descendant-or-self::bar">', 289 equiv = '<Path "descendant-or-self::bar">',
267 xml, 290 input = XML('<root><foo><bar id="1"/></foo><bar id="2"/></root>'),
268 '<bar id="1"/><bar id="2"/>') 291 output = '<bar id="1"/><bar id="2"/>'
292 )
293
294 def test_3step_complex_text(self):
295 xml = XML('<root><item><bar>Some text </bar><baz><bar>in here.</bar></baz></item></root>')
296 self._test_eval(
297 path = 'item/bar/text()',
298 equiv = '<Path "child::item/child::bar/child::text()">',
299 input = xml,
300 output = 'Some text '
301 )
302 self._test_eval(
303 path = 'item//bar/text()',
304 equiv = '<Path "child::item/descendant-or-self::node()/child::bar/child::text()">',
305 input = xml,
306 output = 'Some text in here.'
307 )
269 308
270 def test_node_type_comment(self): 309 def test_node_type_comment(self):
271 xml = XML('<root><!-- commented --></root>') 310 xml = XML('<root><!-- commented --></root>')
272 self._test_expression( 'comment()', 311 self._test_eval(
273 '<Path "child::comment()">', 312 path = 'comment()',
274 xml, 313 equiv = '<Path "child::comment()">',
275 '<!-- commented -->') 314 input = xml,
315 output = '<!-- commented -->'
316 )
276 317
277 def test_node_type_text(self): 318 def test_node_type_text(self):
278 xml = XML('<root>Some text <br/>in here.</root>') 319 xml = XML('<root>Some text <br/>in here.</root>')
279 self._test_expression( 'text()', 320 self._test_eval(
280 '<Path "child::text()">', 321 path = 'text()',
281 xml, 322 equiv = '<Path "child::text()">',
282 'Some text in here.') 323 input = xml,
324 output = 'Some text in here.'
325 )
283 326
284 def test_node_type_node(self): 327 def test_node_type_node(self):
285 xml = XML('<root>Some text <br/>in here.</root>') 328 xml = XML('<root>Some text <br/>in here.</root>')
286 self._test_expression( 'node()', 329 self._test_eval(
287 '<Path "child::node()">', 330 path = 'node()',
288 xml, 331 equiv = '<Path "child::node()">',
289 'Some text <br/>in here.',) 332 input = xml,
333 output = 'Some text <br/>in here.'
334 )
290 335
291 def test_node_type_processing_instruction(self): 336 def test_node_type_processing_instruction(self):
292 xml = XML('<?python x = 2 * 3 ?><root><?php echo("x") ?></root>') 337 xml = XML('<?python x = 2 * 3 ?><root><?php echo("x") ?></root>')
293 338 self._test_eval(
294 self._test_expression( '//processing-instruction()', 339 path = '//processing-instruction()',
295 '<Path "descendant-or-self::processing-instruction()">', 340 equiv = '<Path "descendant-or-self::processing-instruction()">',
296 xml, 341 input = xml,
297 '<?python x = 2 * 3 ?><?php echo("x") ?>') 342 output = '<?python x = 2 * 3 ?><?php echo("x") ?>'
298 343 )
299 self._test_expression( 'processing-instruction()', 344 self._test_eval(
300 '<Path "child::processing-instruction()">', 345 path = 'processing-instruction()',
301 xml, 346 equiv = '<Path "child::processing-instruction()">',
302 '<?php echo("x") ?>') 347 input = xml,
303 348 output = '<?php echo("x") ?>'
304 self._test_expression( 'processing-instruction("php")', 349 )
305 '<Path "child::processing-instruction(\"php\")">', 350 self._test_eval(
306 xml, 351 path = 'processing-instruction("php")',
307 '<?php echo("x") ?>') 352 equiv = '<Path "child::processing-instruction(\"php\")">',
353 input = xml,
354 output = '<?php echo("x") ?>'
355 )
308 356
309 def test_simple_union(self): 357 def test_simple_union(self):
310 xml = XML("""<body>1<br />2<br />3<br /></body>""") 358 xml = XML("""<body>1<br />2<br />3<br /></body>""")
311 self._test_expression( '*|text()', 359 self._test_eval(
312 '<Path "child::*|child::text()">', 360 path = '*|text()',
313 xml, 361 equiv = '<Path "child::*|child::text()">',
314 '1<br/>2<br/>3<br/>') 362 input = xml,
363 output = '1<br/>2<br/>3<br/>'
364 )
315 365
316 def test_predicate_name(self): 366 def test_predicate_name(self):
317 xml = XML('<root><foo/><bar/></root>') 367 xml = XML('<root><foo/><bar/></root>')
318 self._test_expression('*[name()="foo"]', None, xml, '<foo/>') 368 self._test_eval('*[name()="foo"]', input=xml, output='<foo/>')
319 369
320 def test_predicate_localname(self): 370 def test_predicate_localname(self):
321 xml = XML('<root><foo xmlns="NS"/><bar/></root>') 371 xml = XML('<root><foo xmlns="NS"/><bar/></root>')
322 self._test_expression('*[local-name()="foo"]', None, xml, 372 self._test_eval('*[local-name()="foo"]', input=xml,
323 '<foo xmlns="NS"/>') 373 output='<foo xmlns="NS"/>')
324 374
325 def test_predicate_namespace(self): 375 def test_predicate_namespace(self):
326 xml = XML('<root><foo xmlns="NS"/><bar/></root>') 376 xml = XML('<root><foo xmlns="NS"/><bar/></root>')
327 self._test_expression('*[namespace-uri()="NS"]', None, xml, 377 self._test_eval('*[namespace-uri()="NS"]', input=xml,
328 '<foo xmlns="NS"/>') 378 output='<foo xmlns="NS"/>')
329 379
330 def test_predicate_not_name(self): 380 def test_predicate_not_name(self):
331 xml = XML('<root><foo/><bar/></root>') 381 xml = XML('<root><foo/><bar/></root>')
332 self._test_expression('*[not(name()="foo")]', None, xml, '<bar/>') 382 self._test_eval('*[not(name()="foo")]', input=xml,
383 output='<bar/>')
333 384
334 def test_predicate_attr(self): 385 def test_predicate_attr(self):
335 xml = XML('<root><item/><item important="very"/></root>') 386 xml = XML('<root><item/><item important="very"/></root>')
336 self._test_expression('item[@important]', None, xml, 387 self._test_eval('item[@important]', input=xml,
337 '<item important="very"/>') 388 output='<item important="very"/>')
338 self._test_expression('item[@important="very"]', None, xml, 389 self._test_eval('item[@important="very"]', input=xml,
339 '<item important="very"/>') 390 output='<item important="very"/>')
340 391
341 def test_predicate_attr_equality(self): 392 def test_predicate_attr_equality(self):
342 xml = XML('<root><item/><item important="notso"/></root>') 393 xml = XML('<root><item/><item important="notso"/></root>')
343 self._test_expression('item[@important="very"]', None, xml, '') 394 self._test_eval('item[@important="very"]', input=xml, output='')
344 self._test_expression('item[@important!="very"]', None, xml, 395 self._test_eval('item[@important!="very"]', input=xml,
345 '<item/><item important="notso"/>') 396 output='<item/><item important="notso"/>')
346 397
347 def test_predicate_attr_greater_than(self): 398 def test_predicate_attr_greater_than(self):
348 xml = XML('<root><item priority="3"/></root>') 399 xml = XML('<root><item priority="3"/></root>')
349 self._test_expression('item[@priority>3]', None, xml, '') 400 self._test_eval('item[@priority>3]', input=xml, output='')
350 self._test_expression('item[@priority>2]', None, xml, 401 self._test_eval('item[@priority>2]', input=xml,
351 '<item priority="3"/>') 402 output='<item priority="3"/>')
352 403
353 def test_predicate_attr_less_than(self): 404 def test_predicate_attr_less_than(self):
354 xml = XML('<root><item priority="3"/></root>') 405 xml = XML('<root><item priority="3"/></root>')
355 self._test_expression('item[@priority<3]', None, xml, '') 406 self._test_eval('item[@priority<3]', input=xml, output='')
356 self._test_expression('item[@priority<4]', None, xml, 407 self._test_eval('item[@priority<4]', input=xml,
357 '<item priority="3"/>') 408 output='<item priority="3"/>')
358 409
359 def test_predicate_attr_and(self): 410 def test_predicate_attr_and(self):
360 xml = XML('<root><item/><item important="very"/></root>') 411 xml = XML('<root><item/><item important="very"/></root>')
361 self._test_expression('item[@important and @important="very"]', 412 self._test_eval('item[@important and @important="very"]',
362 None, xml, '<item important="very"/>') 413 input=xml, output='<item important="very"/>')
363 self._test_expression('item[@important and @important="notso"]', 414 self._test_eval('item[@important and @important="notso"]',
364 None, xml, '') 415 input=xml, output='')
365 416
366 def test_predicate_attr_or(self): 417 def test_predicate_attr_or(self):
367 xml = XML('<root><item/><item important="very"/></root>') 418 xml = XML('<root><item/><item important="very"/></root>')
368 self._test_expression('item[@urgent or @important]', None, xml, 419 self._test_eval('item[@urgent or @important]', input=xml,
369 '<item important="very"/>') 420 output='<item important="very"/>')
370 self._test_expression('item[@urgent or @notso]', None, xml, '') 421 self._test_eval('item[@urgent or @notso]', input=xml, output='')
371 422
372 def test_predicate_boolean_function(self): 423 def test_predicate_boolean_function(self):
373 xml = XML('<root><foo>bar</foo></root>') 424 xml = XML('<root><foo>bar</foo></root>')
374 self._test_expression('*[boolean("")]', None, xml, '') 425 self._test_eval('*[boolean("")]', input=xml, output='')
375 self._test_expression('*[boolean("yo")]', None, xml, '<foo>bar</foo>') 426 self._test_eval('*[boolean("yo")]', input=xml,
376 self._test_expression('*[boolean(0)]', None, xml, '') 427 output='<foo>bar</foo>')
377 self._test_expression('*[boolean(42)]', None, xml, '<foo>bar</foo>') 428 self._test_eval('*[boolean(0)]', input=xml, output='')
378 self._test_expression('*[boolean(false())]', None, xml, '') 429 self._test_eval('*[boolean(42)]', input=xml,
379 self._test_expression('*[boolean(true())]', None, xml, 430 output='<foo>bar</foo>')
380 '<foo>bar</foo>') 431 self._test_eval('*[boolean(false())]', input=xml, output='')
432 self._test_eval('*[boolean(true())]', input=xml,
433 output='<foo>bar</foo>')
381 434
382 def test_predicate_ceil_function(self): 435 def test_predicate_ceil_function(self):
383 xml = XML('<root><foo>bar</foo></root>') 436 xml = XML('<root><foo>bar</foo></root>')
384 self._test_expression('*[ceiling("4.5")=5]', None, xml, 437 self._test_eval('*[ceiling("4.5")=5]', input=xml,
385 '<foo>bar</foo>') 438 output='<foo>bar</foo>')
386 439
387 def test_predicate_concat_function(self): 440 def test_predicate_concat_function(self):
388 xml = XML('<root><foo>bar</foo></root>') 441 xml = XML('<root><foo>bar</foo></root>')
389 self._test_expression('*[name()=concat("f", "oo")]', None, xml, 442 self._test_eval('*[name()=concat("f", "oo")]', input=xml,
390 '<foo>bar</foo>') 443 output='<foo>bar</foo>')
391 444
392 def test_predicate_contains_function(self): 445 def test_predicate_contains_function(self):
393 xml = XML('<root><foo>bar</foo></root>') 446 xml = XML('<root><foo>bar</foo></root>')
394 self._test_expression('*[contains(name(), "oo")]', None, xml, 447 self._test_eval('*[contains(name(), "oo")]', input=xml,
395 '<foo>bar</foo>') 448 output='<foo>bar</foo>')
396 449
397 def test_predicate_matches_function(self): 450 def test_predicate_matches_function(self):
398 xml = XML('<root><foo>bar</foo><bar>foo</bar></root>') 451 xml = XML('<root><foo>bar</foo><bar>foo</bar></root>')
399 self._test_expression('*[matches(name(), "foo|bar")]', None, xml, 452 self._test_eval('*[matches(name(), "foo|bar")]', input=xml,
400 '<foo>bar</foo><bar>foo</bar>') 453 output='<foo>bar</foo><bar>foo</bar>')
401 454
402 def test_predicate_false_function(self): 455 def test_predicate_false_function(self):
403 xml = XML('<root><foo>bar</foo></root>') 456 xml = XML('<root><foo>bar</foo></root>')
404 self._test_expression('*[false()]', None, xml, '') 457 self._test_eval('*[false()]', input=xml, output='')
405 458
406 def test_predicate_floor_function(self): 459 def test_predicate_floor_function(self):
407 xml = XML('<root><foo>bar</foo></root>') 460 xml = XML('<root><foo>bar</foo></root>')
408 self._test_expression('*[floor("4.5")=4]', None, xml, 461 self._test_eval('*[floor("4.5")=4]', input=xml,
409 '<foo>bar</foo>') 462 output='<foo>bar</foo>')
410 463
411 def test_predicate_normalize_space_function(self): 464 def test_predicate_normalize_space_function(self):
412 xml = XML('<root><foo>bar</foo></root>') 465 xml = XML('<root><foo>bar</foo></root>')
413 self._test_expression('*[normalize-space(" foo bar ")="foo bar"]', 466 self._test_eval('*[normalize-space(" foo bar ")="foo bar"]',
414 None, xml, '<foo>bar</foo>') 467 input=xml, output='<foo>bar</foo>')
415 468
416 def test_predicate_number_function(self): 469 def test_predicate_number_function(self):
417 xml = XML('<root><foo>bar</foo></root>') 470 xml = XML('<root><foo>bar</foo></root>')
418 self._test_expression('*[number("3.0")=3]', None, xml, 471 self._test_eval('*[number("3.0")=3]', input=xml,
419 '<foo>bar</foo>') 472 output='<foo>bar</foo>')
420 self._test_expression('*[number("3.0")=3.0]', None, xml, 473 self._test_eval('*[number("3.0")=3.0]', input=xml,
421 '<foo>bar</foo>') 474 output='<foo>bar</foo>')
422 self._test_expression('*[number("0.1")=.1]', None, xml, 475 self._test_eval('*[number("0.1")=.1]', input=xml,
423 '<foo>bar</foo>') 476 output='<foo>bar</foo>')
424 477
425 def test_predicate_round_function(self): 478 def test_predicate_round_function(self):
426 xml = XML('<root><foo>bar</foo></root>') 479 xml = XML('<root><foo>bar</foo></root>')
427 self._test_expression('*[round("4.4")=4]', None, xml, 480 self._test_eval('*[round("4.4")=4]', input=xml,
428 '<foo>bar</foo>') 481 output='<foo>bar</foo>')
429 self._test_expression('*[round("4.6")=5]', None, xml, 482 self._test_eval('*[round("4.6")=5]', input=xml,
430 '<foo>bar</foo>') 483 output='<foo>bar</foo>')
431 484
432 def test_predicate_starts_with_function(self): 485 def test_predicate_starts_with_function(self):
433 xml = XML('<root><foo>bar</foo></root>') 486 xml = XML('<root><foo>bar</foo></root>')
434 self._test_expression('*[starts-with(name(), "f")]', None, xml, 487 self._test_eval('*[starts-with(name(), "f")]', input=xml,
435 '<foo>bar</foo>') 488 output='<foo>bar</foo>')
436 self._test_expression('*[starts-with(name(), "b")]', None, xml, '') 489 self._test_eval('*[starts-with(name(), "b")]', input=xml,
490 output='')
437 491
438 def test_predicate_string_length_function(self): 492 def test_predicate_string_length_function(self):
439 xml = XML('<root><foo>bar</foo></root>') 493 xml = XML('<root><foo>bar</foo></root>')
440 self._test_expression('*[string-length(name())=3]', None, xml, 494 self._test_eval('*[string-length(name())=3]', input=xml,
441 '<foo>bar</foo>') 495 output='<foo>bar</foo>')
442 496
443 def test_predicate_substring_function(self): 497 def test_predicate_substring_function(self):
444 xml = XML('<root><foo>bar</foo></root>') 498 xml = XML('<root><foo>bar</foo></root>')
445 self._test_expression('*[substring(name(), 1)="oo"]', None, xml, 499 self._test_eval('*[substring(name(), 1)="oo"]', input=xml,
446 '<foo>bar</foo>') 500 output='<foo>bar</foo>')
447 self._test_expression('*[substring(name(), 1, 1)="o"]', None, xml, 501 self._test_eval('*[substring(name(), 1, 1)="o"]', input=xml,
448 '<foo>bar</foo>') 502 output='<foo>bar</foo>')
449 503
450 def test_predicate_substring_after_function(self): 504 def test_predicate_substring_after_function(self):
451 xml = XML('<root><foo>bar</foo></root>') 505 xml = XML('<root><foo>bar</foo></root>')
452 self._test_expression('*[substring-after(name(), "f")="oo"]', None, xml, 506 self._test_eval('*[substring-after(name(), "f")="oo"]', input=xml,
453 '<foo>bar</foo>') 507 output='<foo>bar</foo>')
454 508
455 def test_predicate_substring_before_function(self): 509 def test_predicate_substring_before_function(self):
456 xml = XML('<root><foo>bar</foo></root>') 510 xml = XML('<root><foo>bar</foo></root>')
457 self._test_expression('*[substring-before(name(), "oo")="f"]', 511 self._test_eval('*[substring-before(name(), "oo")="f"]',
458 None, xml, '<foo>bar</foo>') 512 input=xml, output='<foo>bar</foo>')
459 513
460 def test_predicate_translate_function(self): 514 def test_predicate_translate_function(self):
461 xml = XML('<root><foo>bar</foo></root>') 515 xml = XML('<root><foo>bar</foo></root>')
462 self._test_expression('*[translate(name(), "fo", "ba")="baa"]', 516 self._test_eval('*[translate(name(), "fo", "ba")="baa"]',
463 None, xml, '<foo>bar</foo>') 517 input=xml, output='<foo>bar</foo>')
464 518
465 def test_predicate_true_function(self): 519 def test_predicate_true_function(self):
466 xml = XML('<root><foo>bar</foo></root>') 520 xml = XML('<root><foo>bar</foo></root>')
467 self._test_expression('*[true()]', None, xml, '<foo>bar</foo>') 521 self._test_eval('*[true()]', input=xml, output='<foo>bar</foo>')
468 522
469 def test_predicate_variable(self): 523 def test_predicate_variable(self):
470 xml = XML('<root><foo>bar</foo></root>') 524 xml = XML('<root><foo>bar</foo></root>')
471 variables = {'bar': 'foo'} 525 self._test_eval(
472 self._test_expression('*[name()=$bar]', None, xml, '<foo>bar</foo>', 526 path = '*[name()=$bar]',
473 variables = variables) 527 input = xml,
528 output = '<foo>bar</foo>',
529 variables = {'bar': 'foo'}
530 )
474 531
475 def test_predicate_position(self): 532 def test_predicate_position(self):
476 xml = XML('<root><foo id="a1"/><foo id="a2"/><foo id="a3"/></root>') 533 xml = XML('<root><foo id="a1"/><foo id="a2"/><foo id="a3"/></root>')
477 self._test_expression('*[2]', None, xml, '<foo id="a2"/>') 534 self._test_eval('*[2]', input=xml, output='<foo id="a2"/>')
478 535
479 def test_predicate_attr_and_position(self): 536 def test_predicate_attr_and_position(self):
480 xml = XML('<root><foo/><foo id="a1"/><foo id="a2"/></root>') 537 xml = XML('<root><foo/><foo id="a1"/><foo id="a2"/></root>')
481 self._test_expression('*[@id][2]', None, xml, '<foo id="a2"/>') 538 self._test_eval('*[@id][2]', input=xml, output='<foo id="a2"/>')
482 539
483 def test_predicate_position_and_attr(self): 540 def test_predicate_position_and_attr(self):
484 xml = XML('<root><foo/><foo id="a1"/><foo id="a2"/></root>') 541 xml = XML('<root><foo/><foo id="a1"/><foo id="a2"/></root>')
485 self._test_expression('*[1][@id]', None, xml, '') 542 self._test_eval('*[1][@id]', input=xml, output='')
486 self._test_expression('*[2][@id]', None, xml, '<foo id="a1"/>') 543 self._test_eval('*[2][@id]', input=xml, output='<foo id="a1"/>')
487 544
488 def test_predicate_advanced_position(self): 545 def test_predicate_advanced_position(self):
489 xml = XML('<root><a><b><c><d><e/></d></c></b></a></root>') 546 xml = XML('<root><a><b><c><d><e/></d></c></b></a></root>')
490 self._test_expression( 'descendant-or-self::*/' 547 self._test_eval( 'descendant-or-self::*/'
491 'descendant-or-self::*/' 548 'descendant-or-self::*/'
492 'descendant-or-self::*[2]/' 549 'descendant-or-self::*[2]/'
493 'self::*/descendant::*[3]', None, xml, 550 'self::*/descendant::*[3]', input=xml,
494 '<d><e/></d>') 551 output='<d><e/></d>')
495 552
496 def test_predicate_child_position(self): 553 def test_predicate_child_position(self):
497 xml = XML('\ 554 xml = XML('\
498 <root><a><b>1</b><b>2</b><b>3</b></a><a><b>4</b><b>5</b></a></root>') 555 <root><a><b>1</b><b>2</b><b>3</b></a><a><b>4</b><b>5</b></a></root>')
499 self._test_expression('//a/b[2]', None, xml, '<b>2</b><b>5</b>') 556 self._test_eval('//a/b[2]', input=xml, output='<b>2</b><b>5</b>')
500 self._test_expression('//a/b[3]', None, xml, '<b>3</b>') 557 self._test_eval('//a/b[3]', input=xml, output='<b>3</b>')
501 558
502 def test_name_with_namespace(self): 559 def test_name_with_namespace(self):
503 xml = XML('<root xmlns:f="FOO"><f:foo>bar</f:foo></root>') 560 xml = XML('<root xmlns:f="FOO"><f:foo>bar</f:foo></root>')
504 self._test_expression('f:foo', '<Path "child::f:foo">', xml, 561 self._test_eval(
505 '<foo xmlns="FOO">bar</foo>', 562 path = 'f:foo',
506 namespaces = {'f': 'FOO'}) 563 equiv = '<Path "child::f:foo">',
564 input = xml,
565 output = '<foo xmlns="FOO">bar</foo>',
566 namespaces = {'f': 'FOO'}
567 )
507 568
508 def test_wildcard_with_namespace(self): 569 def test_wildcard_with_namespace(self):
509 xml = XML('<root xmlns:f="FOO"><f:foo>bar</f:foo></root>') 570 xml = XML('<root xmlns:f="FOO"><f:foo>bar</f:foo></root>')
510 self._test_expression('f:*', '<Path "child::f:*">', xml, 571 self._test_eval(
511 '<foo xmlns="FOO">bar</foo>', 572 path = 'f:*',
512 namespaces = {'f': 'FOO'}) 573 equiv = '<Path "child::f:*">',
574 input = xml,
575 output = '<foo xmlns="FOO">bar</foo>',
576 namespaces = {'f': 'FOO'}
577 )
513 578
514 def test_predicate_termination(self): 579 def test_predicate_termination(self):
515 """ 580 """
516 Verify that a patch matching the self axis with a predicate doesn't 581 Verify that a patch matching the self axis with a predicate doesn't
517 cause an infinite loop. See <http://genshi.edgewall.org/ticket/82>. 582 cause an infinite loop. See <http://genshi.edgewall.org/ticket/82>.
518 """ 583 """
519 xml = XML('<ul flag="1"><li>a</li><li>b</li></ul>') 584 xml = XML('<ul flag="1"><li>a</li><li>b</li></ul>')
520 self._test_expression('.[@flag="1"]/*', None, xml, 585 self._test_eval('.[@flag="1"]/*', input=xml,
521 '<li>a</li><li>b</li>') 586 output='<li>a</li><li>b</li>')
522 587
523 xml = XML('<ul flag="1"><li>a</li><li>b</li></ul>') 588 xml = XML('<ul flag="1"><li>a</li><li>b</li></ul>')
524 self._test_expression('.[@flag="0"]/*', None, xml, '') 589 self._test_eval('.[@flag="0"]/*', input=xml, output='')
525 590
526 def test_attrname_with_namespace(self): 591 def test_attrname_with_namespace(self):
527 xml = XML('<root xmlns:f="FOO"><foo f:bar="baz"/></root>') 592 xml = XML('<root xmlns:f="FOO"><foo f:bar="baz"/></root>')
528 self._test_expression('foo[@f:bar]', None, xml, 593 self._test_eval('foo[@f:bar]', input=xml,
529 '<foo xmlns:ns1="FOO" ns1:bar="baz"/>', 594 output='<foo xmlns:ns1="FOO" ns1:bar="baz"/>',
530 namespaces={'f': 'FOO'}) 595 namespaces={'f': 'FOO'})
531 596
532 def test_attrwildcard_with_namespace(self): 597 def test_attrwildcard_with_namespace(self):
533 xml = XML('<root xmlns:f="FOO"><foo f:bar="baz"/></root>') 598 xml = XML('<root xmlns:f="FOO"><foo f:bar="baz"/></root>')
534 self._test_expression('foo[@f:*]', None, xml, 599 self._test_eval('foo[@f:*]', input=xml,
535 '<foo xmlns:ns1="FOO" ns1:bar="baz"/>', 600 output='<foo xmlns:ns1="FOO" ns1:bar="baz"/>',
536 namespaces={'f': 'FOO'}) 601 namespaces={'f': 'FOO'})
602
537 def test_self_and_descendant(self): 603 def test_self_and_descendant(self):
538 xml = XML('<root><foo/></root>') 604 xml = XML('<root><foo/></root>')
539 self._test_expression('self::root', None, xml, '<root><foo/></root>') 605 self._test_eval('self::root', input=xml, output='<root><foo/></root>')
540 self._test_expression('self::foo', None, xml, '') 606 self._test_eval('self::foo', input=xml, output='')
541 self._test_expression('descendant::root', None, xml, '') 607 self._test_eval('descendant::root', input=xml, output='')
542 self._test_expression('descendant::foo', None, xml, '<foo/>') 608 self._test_eval('descendant::foo', input=xml, output='<foo/>')
543 self._test_expression('descendant-or-self::root', None, xml, 609 self._test_eval('descendant-or-self::root', input=xml,
544 '<root><foo/></root>') 610 output='<root><foo/></root>')
545 self._test_expression('descendant-or-self::foo', None, xml, '<foo/>') 611 self._test_eval('descendant-or-self::foo', input=xml, output='<foo/>')
546 612
547 def test_long_simple_paths(self): 613 def test_long_simple_paths(self):
548 xml = XML('<root><a><b><a><d><a><b><a><b><a><b><a><c>!' 614 xml = XML('<root><a><b><a><d><a><b><a><b><a><b><a><c>!'
549 '</c></a></b></a></b></a></b></a></d></a></b></a></root>') 615 '</c></a></b></a></b></a></b></a></d></a></b></a></root>')
550 self._test_expression('//a/b/a/b/a/c', None, xml, '<c>!</c>') 616 self._test_eval('//a/b/a/b/a/c', input=xml, output='<c>!</c>')
551 self._test_expression('//a/b/a/c', None, xml, '<c>!</c>') 617 self._test_eval('//a/b/a/c', input=xml, output='<c>!</c>')
552 self._test_expression('//a/c', None, xml, '<c>!</c>') 618 self._test_eval('//a/c', input=xml, output='<c>!</c>')
553 self._test_expression('//c', None, xml, '<c>!</c>') 619 self._test_eval('//c', input=xml, output='<c>!</c>')
554 # Please note that a//b is NOT the same as a/descendant::b 620 # Please note that a//b is NOT the same as a/descendant::b
555 # it is a/descendant-or-self::node()/b, which SimplePathStrategy 621 # it is a/descendant-or-self::node()/b, which SimplePathStrategy
556 # does NOT support 622 # does NOT support
557 self._test_expression('a/b/descendant::a/c', None, xml, '<c>!</c>') 623 self._test_eval('a/b/descendant::a/c', input=xml, output='<c>!</c>')
558 self._test_expression('a/b/descendant::a/d/descendant::a/c', 624 self._test_eval('a/b/descendant::a/d/descendant::a/c',
559 None, xml, '<c>!</c>') 625 input=xml, output='<c>!</c>')
560 self._test_expression('a/b/descendant::a/d/a/c', None, xml, '') 626 self._test_eval('a/b/descendant::a/d/a/c', input=xml, output='')
561 self._test_expression('//d/descendant::b/descendant::b/descendant::b' 627 self._test_eval('//d/descendant::b/descendant::b/descendant::b'
562 '/descendant::c', None, xml, '<c>!</c>') 628 '/descendant::c', input=xml, output='<c>!</c>')
563 self._test_expression('//d/descendant::b/descendant::b/descendant::b' 629 self._test_eval('//d/descendant::b/descendant::b/descendant::b'
564 '/descendant::b/descendant::c', None, xml, '') 630 '/descendant::b/descendant::c', input=xml,
631 output='')
632
565 def _test_support(self, strategy_class, text): 633 def _test_support(self, strategy_class, text):
566 path = PathParser(text, None, -1).parse()[0] 634 path = PathParser(text, None, -1).parse()[0]
567 return strategy_class.supports(path) 635 return strategy_class.supports(path)
636
568 def test_simple_strategy_support(self): 637 def test_simple_strategy_support(self):
569 self.assert_(self._test_support(SimplePathStrategy, 'a/b')) 638 self.assert_(self._test_support(SimplePathStrategy, 'a/b'))
570 self.assert_(self._test_support(SimplePathStrategy, 'self::a/b')) 639 self.assert_(self._test_support(SimplePathStrategy, 'self::a/b'))
571 self.assert_(self._test_support(SimplePathStrategy, 'descendant::a/b')) 640 self.assert_(self._test_support(SimplePathStrategy, 'descendant::a/b'))
572 self.assert_(self._test_support(SimplePathStrategy, 641 self.assert_(self._test_support(SimplePathStrategy,
580 self.assert_(not self._test_support(SimplePathStrategy, 'node()/@a')) 649 self.assert_(not self._test_support(SimplePathStrategy, 'node()/@a'))
581 self.assert_(not self._test_support(SimplePathStrategy, '@a')) 650 self.assert_(not self._test_support(SimplePathStrategy, '@a'))
582 self.assert_(not self._test_support(SimplePathStrategy, 'foo:bar')) 651 self.assert_(not self._test_support(SimplePathStrategy, 'foo:bar'))
583 self.assert_(not self._test_support(SimplePathStrategy, 'a/@foo:bar')) 652 self.assert_(not self._test_support(SimplePathStrategy, 'a/@foo:bar'))
584 653
654 def _test_strategies(self, input, path, output,
655 namespaces=None, variables=None):
656 for strategy in self.strategies:
657 if not strategy.supports(path):
658 continue
659 s = strategy(path)
660 rendered = FakePath(s).select(input, namespaces=namespaces,
661 variables=variables) \
662 .render(encoding=None)
663 msg = 'Bad render using %s strategy' % str(strategy)
664 msg += '\nExpected:\t%r' % output
665 msg += '\nRendered:\t%r' % rendered
666 self.assertEqual(output, rendered, msg)
667
668 def _test_eval(self, path, equiv=None, input=None, output='',
669 namespaces=None, variables=None):
670 path = Path(path)
671 if equiv is not None:
672 self.assertEqual(equiv, repr(path))
673
674 if input is None:
675 return
676
677 rendered = path.select(input, namespaces=namespaces,
678 variables=variables).render(encoding=None)
679 msg = 'Bad output using whole path'
680 msg += '\nExpected:\t%r' % output
681 msg += '\nRendered:\t%r' % rendered
682 self.assertEqual(output, rendered, msg)
683
684 if len(path.paths) == 1:
685 self._test_strategies(input, path.paths[0], output,
686 namespaces=namespaces, variables=variables)
687
688
585 def suite(): 689 def suite():
586 suite = unittest.TestSuite() 690 suite = unittest.TestSuite()
587 suite.addTest(doctest.DocTestSuite(Path.__module__)) 691 suite.addTest(doctest.DocTestSuite(Path.__module__))
588 suite.addTest(unittest.makeSuite(PathTestCase, 'test')) 692 suite.addTest(unittest.makeSuite(PathTestCase, 'test'))
589 return suite 693 return suite
590 694
695
591 if __name__ == '__main__': 696 if __name__ == '__main__':
592 unittest.main(defaultTest='suite') 697 unittest.main(defaultTest='suite')
Copyright (C) 2012-2017 Edgewall Software