comparison genshi/template/tests/directives.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
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 # 2 #
3 # Copyright (C) 2006-2008 Edgewall Software 3 # Copyright (C) 2006-2010 Edgewall Software
4 # All rights reserved. 4 # All rights reserved.
5 # 5 #
6 # This software is licensed as described in the file COPYING, which 6 # This software is licensed as described in the file COPYING, which
7 # you should have received as part of this distribution. The terms 7 # you should have received as part of this distribution. The terms
8 # are also available at http://genshi.edgewall.org/wiki/License. 8 # are also available at http://genshi.edgewall.org/wiki/License.
10 # This software consists of voluntary contributions made by many 10 # This software consists of voluntary contributions made by many
11 # individuals. For the exact contribution history, see the revision 11 # individuals. For the exact contribution history, see the revision
12 # history and logs, available at http://genshi.edgewall.org/log/. 12 # history and logs, available at http://genshi.edgewall.org/log/.
13 13
14 import doctest 14 import doctest
15 import re
15 import sys 16 import sys
16 import unittest 17 import unittest
17 18
18 from genshi.template import directives, MarkupTemplate, TextTemplate, \ 19 from genshi.template import directives, MarkupTemplate, TextTemplate, \
19 TemplateRuntimeError, TemplateSyntaxError 20 TemplateRuntimeError, TemplateSyntaxError
30 <elem py:for="item in items" py:attrs="item"/> 31 <elem py:for="item in items" py:attrs="item"/>
31 </doc>""") 32 </doc>""")
32 items = [{'id': 1, 'class': 'foo'}, {'id': 2, 'class': 'bar'}] 33 items = [{'id': 1, 'class': 'foo'}, {'id': 2, 'class': 'bar'}]
33 self.assertEqual("""<doc> 34 self.assertEqual("""<doc>
34 <elem id="1" class="foo"/><elem id="2" class="bar"/> 35 <elem id="1" class="foo"/><elem id="2" class="bar"/>
35 </doc>""", str(tmpl.generate(items=items))) 36 </doc>""", tmpl.generate(items=items).render(encoding=None))
36 37
37 def test_update_existing_attr(self): 38 def test_update_existing_attr(self):
38 """ 39 """
39 Verify that an attribute value that evaluates to `None` removes an 40 Verify that an attribute value that evaluates to `None` removes an
40 existing attribute of that name. 41 existing attribute of that name.
42 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/"> 43 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
43 <elem class="foo" py:attrs="{'class': 'bar'}"/> 44 <elem class="foo" py:attrs="{'class': 'bar'}"/>
44 </doc>""") 45 </doc>""")
45 self.assertEqual("""<doc> 46 self.assertEqual("""<doc>
46 <elem class="bar"/> 47 <elem class="bar"/>
47 </doc>""", str(tmpl.generate())) 48 </doc>""", tmpl.generate().render(encoding=None))
48 49
49 def test_remove_existing_attr(self): 50 def test_remove_existing_attr(self):
50 """ 51 """
51 Verify that an attribute value that evaluates to `None` removes an 52 Verify that an attribute value that evaluates to `None` removes an
52 existing attribute of that name. 53 existing attribute of that name.
54 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/"> 55 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
55 <elem class="foo" py:attrs="{'class': None}"/> 56 <elem class="foo" py:attrs="{'class': None}"/>
56 </doc>""") 57 </doc>""")
57 self.assertEqual("""<doc> 58 self.assertEqual("""<doc>
58 <elem/> 59 <elem/>
59 </doc>""", str(tmpl.generate())) 60 </doc>""", tmpl.generate().render(encoding=None))
60 61
61 62
62 class ChooseDirectiveTestCase(unittest.TestCase): 63 class ChooseDirectiveTestCase(unittest.TestCase):
63 """Tests for the `py:choose` template directive and the complementary 64 """Tests for the `py:choose` template directive and the complementary
64 directives `py:when` and `py:otherwise`.""" 65 directives `py:when` and `py:otherwise`."""
73 <span py:when="2 == 2">2</span> 74 <span py:when="2 == 2">2</span>
74 <span py:when="3 == 3">3</span> 75 <span py:when="3 == 3">3</span>
75 </div>""") 76 </div>""")
76 self.assertEqual("""<div> 77 self.assertEqual("""<div>
77 <span>1</span> 78 <span>1</span>
78 </div>""", str(tmpl.generate())) 79 </div>""", tmpl.generate().render(encoding=None))
79 80
80 def test_otherwise(self): 81 def test_otherwise(self):
81 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/" py:choose=""> 82 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/" py:choose="">
82 <span py:when="False">hidden</span> 83 <span py:when="False">hidden</span>
83 <span py:otherwise="">hello</span> 84 <span py:otherwise="">hello</span>
84 </div>""") 85 </div>""")
85 self.assertEqual("""<div> 86 self.assertEqual("""<div>
86 <span>hello</span> 87 <span>hello</span>
87 </div>""", str(tmpl.generate())) 88 </div>""", tmpl.generate().render(encoding=None))
88 89
89 def test_nesting(self): 90 def test_nesting(self):
90 """ 91 """
91 Verify that `py:choose` blocks can be nested: 92 Verify that `py:choose` blocks can be nested:
92 """ 93 """
102 <div> 103 <div>
103 <div> 104 <div>
104 <span>3</span> 105 <span>3</span>
105 </div> 106 </div>
106 </div> 107 </div>
107 </doc>""", str(tmpl.generate())) 108 </doc>""", tmpl.generate().render(encoding=None))
108 109
109 def test_complex_nesting(self): 110 def test_complex_nesting(self):
110 """ 111 """
111 Verify more complex nesting. 112 Verify more complex nesting.
112 """ 113 """
122 <div> 123 <div>
123 <div> 124 <div>
124 <span>OK</span> 125 <span>OK</span>
125 </div> 126 </div>
126 </div> 127 </div>
127 </doc>""", str(tmpl.generate())) 128 </doc>""", tmpl.generate().render(encoding=None))
128 129
129 def test_complex_nesting_otherwise(self): 130 def test_complex_nesting_otherwise(self):
130 """ 131 """
131 Verify more complex nesting using otherwise. 132 Verify more complex nesting using otherwise.
132 """ 133 """
142 <div> 143 <div>
143 <div> 144 <div>
144 <span>OK</span> 145 <span>OK</span>
145 </div> 146 </div>
146 </div> 147 </div>
147 </doc>""", str(tmpl.generate())) 148 </doc>""", tmpl.generate().render(encoding=None))
148 149
149 def test_when_with_strip(self): 150 def test_when_with_strip(self):
150 """ 151 """
151 Verify that a when directive with a strip directive actually strips of 152 Verify that a when directive with a strip directive actually strips of
152 the outer element. 153 the outer element.
156 <span py:otherwise="">foo</span> 157 <span py:otherwise="">foo</span>
157 </div> 158 </div>
158 </doc>""") 159 </doc>""")
159 self.assertEqual("""<doc> 160 self.assertEqual("""<doc>
160 <span>foo</span> 161 <span>foo</span>
161 </doc>""", str(tmpl.generate())) 162 </doc>""", tmpl.generate().render(encoding=None))
162 163
163 def test_when_outside_choose(self): 164 def test_when_outside_choose(self):
164 """ 165 """
165 Verify that a `when` directive outside of a `choose` directive is 166 Verify that a `when` directive outside of a `choose` directive is
166 reported as an error. 167 reported as an error.
203 <py:when>foo</py:when> 204 <py:when>foo</py:when>
204 </div> 205 </div>
205 </doc>""") 206 </doc>""")
206 self.assertEqual("""<doc> 207 self.assertEqual("""<doc>
207 foo 208 foo
208 </doc>""", str(tmpl.generate(foo='Yeah'))) 209 </doc>""", tmpl.generate(foo='Yeah').render(encoding=None))
209 210
210 def test_otherwise_without_test(self): 211 def test_otherwise_without_test(self):
211 """ 212 """
212 Verify that an `otherwise` directive can be used without a `test` 213 Verify that an `otherwise` directive can be used without a `test`
213 attribute. 214 attribute.
217 <py:otherwise>foo</py:otherwise> 218 <py:otherwise>foo</py:otherwise>
218 </div> 219 </div>
219 </doc>""") 220 </doc>""")
220 self.assertEqual("""<doc> 221 self.assertEqual("""<doc>
221 foo 222 foo
222 </doc>""", str(tmpl.generate())) 223 </doc>""", tmpl.generate().render(encoding=None))
223 224
224 def test_as_element(self): 225 def test_as_element(self):
225 """ 226 """
226 Verify that the directive can also be used as an element. 227 Verify that the directive can also be used as an element.
227 """ 228 """
232 <py:when test="3 == 3">3</py:when> 233 <py:when test="3 == 3">3</py:when>
233 </py:choose> 234 </py:choose>
234 </doc>""") 235 </doc>""")
235 self.assertEqual("""<doc> 236 self.assertEqual("""<doc>
236 1 237 1
237 </doc>""", str(tmpl.generate())) 238 </doc>""", tmpl.generate().render(encoding=None))
238 239
239 def test_in_text_template(self): 240 def test_in_text_template(self):
240 """ 241 """
241 Verify that the directive works as expected in a text template. 242 Verify that the directive works as expected in a text template.
242 """ 243 """
249 #end 250 #end
250 #when 3 == 3 251 #when 3 == 3
251 3 252 3
252 #end 253 #end
253 #end""") 254 #end""")
254 self.assertEqual(""" 1\n""", str(tmpl.generate())) 255 self.assertEqual(""" 1\n""",
256 tmpl.generate().render(encoding=None))
255 257
256 258
257 class DefDirectiveTestCase(unittest.TestCase): 259 class DefDirectiveTestCase(unittest.TestCase):
258 """Tests for the `py:def` template directive.""" 260 """Tests for the `py:def` template directive."""
259 261
268 </div> 270 </div>
269 ${echo('foo')} 271 ${echo('foo')}
270 </doc>""") 272 </doc>""")
271 self.assertEqual("""<doc> 273 self.assertEqual("""<doc>
272 <b>foo</b> 274 <b>foo</b>
273 </doc>""", str(tmpl.generate())) 275 </doc>""", tmpl.generate().render(encoding=None))
274 276
275 def test_exec_in_replace(self): 277 def test_exec_in_replace(self):
276 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 278 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
277 <p py:def="echo(greeting, name='world')" class="message"> 279 <p py:def="echo(greeting, name='world')" class="message">
278 ${greeting}, ${name}! 280 ${greeting}, ${name}!
281 </div>""") 283 </div>""")
282 self.assertEqual("""<div> 284 self.assertEqual("""<div>
283 <p class="message"> 285 <p class="message">
284 hello, world! 286 hello, world!
285 </p> 287 </p>
286 </div>""", str(tmpl.generate())) 288 </div>""", tmpl.generate().render(encoding=None))
287 289
288 def test_as_element(self): 290 def test_as_element(self):
289 """ 291 """
290 Verify that the directive can also be used as an element. 292 Verify that the directive can also be used as an element.
291 """ 293 """
295 </py:def> 297 </py:def>
296 ${echo('foo')} 298 ${echo('foo')}
297 </doc>""") 299 </doc>""")
298 self.assertEqual("""<doc> 300 self.assertEqual("""<doc>
299 <b>foo</b> 301 <b>foo</b>
300 </doc>""", str(tmpl.generate())) 302 </doc>""", tmpl.generate().render(encoding=None))
301 303
302 def test_nested_defs(self): 304 def test_nested_defs(self):
303 """ 305 """
304 Verify that a template function defined inside a conditional block can 306 Verify that a template function defined inside a conditional block can
305 be called from outside that block. 307 be called from outside that block.
313 </py:if> 315 </py:if>
314 ${echo('foo')} 316 ${echo('foo')}
315 </doc>""") 317 </doc>""")
316 self.assertEqual("""<doc> 318 self.assertEqual("""<doc>
317 <strong>foo</strong> 319 <strong>foo</strong>
318 </doc>""", str(tmpl.generate(semantic=True))) 320 </doc>""", tmpl.generate(semantic=True).render(encoding=None))
319 321
320 def test_function_with_default_arg(self): 322 def test_function_with_default_arg(self):
321 """ 323 """
322 Verify that keyword arguments work with `py:def` directives. 324 Verify that keyword arguments work with `py:def` directives.
323 """ 325 """
325 <b py:def="echo(what, bold=False)" py:strip="not bold">${what}</b> 327 <b py:def="echo(what, bold=False)" py:strip="not bold">${what}</b>
326 ${echo('foo')} 328 ${echo('foo')}
327 </doc>""") 329 </doc>""")
328 self.assertEqual("""<doc> 330 self.assertEqual("""<doc>
329 foo 331 foo
330 </doc>""", str(tmpl.generate())) 332 </doc>""", tmpl.generate().render(encoding=None))
331 333
332 def test_invocation_in_attribute(self): 334 def test_invocation_in_attribute(self):
333 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/"> 335 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
334 <py:def function="echo(what)">${what or 'something'}</py:def> 336 <py:def function="echo(what)">${what or 'something'}</py:def>
335 <p class="${echo('foo')}">bar</p> 337 <p class="${echo('foo')}">bar</p>
336 </doc>""") 338 </doc>""")
337 self.assertEqual("""<doc> 339 self.assertEqual("""<doc>
338 <p class="foo">bar</p> 340 <p class="foo">bar</p>
339 </doc>""", str(tmpl.generate())) 341 </doc>""", tmpl.generate().render(encoding=None))
340 342
341 def test_invocation_in_attribute_none(self): 343 def test_invocation_in_attribute_none(self):
342 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/"> 344 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
343 <py:def function="echo()">${None}</py:def> 345 <py:def function="echo()">${None}</py:def>
344 <p class="${echo()}">bar</p> 346 <p class="${echo()}">bar</p>
345 </doc>""") 347 </doc>""")
346 self.assertEqual("""<doc> 348 self.assertEqual("""<doc>
347 <p>bar</p> 349 <p>bar</p>
348 </doc>""", str(tmpl.generate())) 350 </doc>""", tmpl.generate().render(encoding=None))
349 351
350 def test_function_raising_typeerror(self): 352 def test_function_raising_typeerror(self):
351 def badfunc(): 353 def badfunc():
352 raise TypeError 354 raise TypeError
353 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> 355 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
366 <title>${maketitle(True)}</title> 368 <title>${maketitle(True)}</title>
367 </head> 369 </head>
368 </doc>""") 370 </doc>""")
369 self.assertEqual("""<doc> 371 self.assertEqual("""<doc>
370 <head><title>True</title></head> 372 <head><title>True</title></head>
371 </doc>""", str(tmpl.generate())) 373 </doc>""", tmpl.generate().render(encoding=None))
372 374
373 def test_in_text_template(self): 375 def test_in_text_template(self):
374 """ 376 """
375 Verify that the directive works as expected in a text template. 377 Verify that the directive works as expected in a text template.
376 """ 378 """
381 ${echo('Hi', name='you')} 383 ${echo('Hi', name='you')}
382 """) 384 """)
383 self.assertEqual(""" 385 self.assertEqual("""
384 Hi, you! 386 Hi, you!
385 387
386 """, str(tmpl.generate())) 388 """, tmpl.generate().render(encoding=None))
387 389
388 def test_function_with_star_args(self): 390 def test_function_with_star_args(self):
389 """ 391 """
390 Verify that a named template function using "star arguments" works as 392 Verify that a named template function using "star arguments" works as
391 expected. 393 expected.
400 self.assertEqual("""<doc> 402 self.assertEqual("""<doc>
401 <div> 403 <div>
402 [1, 2] 404 [1, 2]
403 {'a': 3, 'b': 4} 405 {'a': 3, 'b': 4}
404 </div> 406 </div>
405 </doc>""", str(tmpl.generate())) 407 </doc>""", tmpl.generate().render(encoding=None))
406 408
407 409
408 class ForDirectiveTestCase(unittest.TestCase): 410 class ForDirectiveTestCase(unittest.TestCase):
409 """Tests for the `py:for` template directive.""" 411 """Tests for the `py:for` template directive."""
410 412
422 <b>1</b> 424 <b>1</b>
423 <b>2</b> 425 <b>2</b>
424 <b>3</b> 426 <b>3</b>
425 <b>4</b> 427 <b>4</b>
426 <b>5</b> 428 <b>5</b>
427 </doc>""", str(tmpl.generate(items=range(1, 6)))) 429 </doc>""", tmpl.generate(items=range(1, 6)).render(encoding=None))
428 430
429 def test_as_element(self): 431 def test_as_element(self):
430 """ 432 """
431 Verify that the directive can also be used as an element. 433 Verify that the directive can also be used as an element.
432 """ 434 """
439 <b>1</b> 441 <b>1</b>
440 <b>2</b> 442 <b>2</b>
441 <b>3</b> 443 <b>3</b>
442 <b>4</b> 444 <b>4</b>
443 <b>5</b> 445 <b>5</b>
444 </doc>""", str(tmpl.generate(items=range(1, 6)))) 446 </doc>""", tmpl.generate(items=range(1, 6)).render(encoding=None))
445 447
446 def test_multi_assignment(self): 448 def test_multi_assignment(self):
447 """ 449 """
448 Verify that assignment to tuples works correctly. 450 Verify that assignment to tuples works correctly.
449 """ 451 """
453 </py:for> 455 </py:for>
454 </doc>""") 456 </doc>""")
455 self.assertEqual("""<doc> 457 self.assertEqual("""<doc>
456 <p>key=a, value=1</p> 458 <p>key=a, value=1</p>
457 <p>key=b, value=2</p> 459 <p>key=b, value=2</p>
458 </doc>""", str(tmpl.generate(items=dict(a=1, b=2).items()))) 460 </doc>""", tmpl.generate(items=dict(a=1, b=2).items())
461 .render(encoding=None))
459 462
460 def test_nested_assignment(self): 463 def test_nested_assignment(self):
461 """ 464 """
462 Verify that assignment to nested tuples works correctly. 465 Verify that assignment to nested tuples works correctly.
463 """ 466 """
467 </py:for> 470 </py:for>
468 </doc>""") 471 </doc>""")
469 self.assertEqual("""<doc> 472 self.assertEqual("""<doc>
470 <p>0: key=a, value=1</p> 473 <p>0: key=a, value=1</p>
471 <p>1: key=b, value=2</p> 474 <p>1: key=b, value=2</p>
472 </doc>""", str(tmpl.generate(items=enumerate(dict(a=1, b=2).items())))) 475 </doc>""", tmpl.generate(items=enumerate(dict(a=1, b=2).items()))
476 .render(encoding=None))
473 477
474 def test_not_iterable(self): 478 def test_not_iterable(self):
475 """ 479 """
476 Verify that assignment to nested tuples works correctly. 480 Verify that assignment to nested tuples works correctly.
477 """ 481 """
526 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/"> 530 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
527 <b py:if="foo" py:strip="">${bar}</b> 531 <b py:if="foo" py:strip="">${bar}</b>
528 </doc>""") 532 </doc>""")
529 self.assertEqual("""<doc> 533 self.assertEqual("""<doc>
530 Hello 534 Hello
531 </doc>""", str(tmpl.generate(foo=True, bar='Hello'))) 535 </doc>""", tmpl.generate(foo=True, bar='Hello').render(encoding=None))
532 536
533 def test_as_element(self): 537 def test_as_element(self):
534 """ 538 """
535 Verify that the directive can also be used as an element. 539 Verify that the directive can also be used as an element.
536 """ 540 """
537 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/"> 541 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
538 <py:if test="foo">${bar}</py:if> 542 <py:if test="foo">${bar}</py:if>
539 </doc>""") 543 </doc>""")
540 self.assertEqual("""<doc> 544 self.assertEqual("""<doc>
541 Hello 545 Hello
542 </doc>""", str(tmpl.generate(foo=True, bar='Hello'))) 546 </doc>""", tmpl.generate(foo=True, bar='Hello').render(encoding=None))
543 547
544 548
545 class MatchDirectiveTestCase(unittest.TestCase): 549 class MatchDirectiveTestCase(unittest.TestCase):
546 """Tests for the `py:match` template directive.""" 550 """Tests for the `py:match` template directive."""
547 551
556 </elem> 560 </elem>
557 <elem>Hey Joe</elem> 561 <elem>Hey Joe</elem>
558 </doc>""") 562 </doc>""")
559 self.assertEqual("""<doc> 563 self.assertEqual("""<doc>
560 <div class="elem">Hey Joe</div> 564 <div class="elem">Hey Joe</div>
561 </doc>""", str(tmpl.generate())) 565 </doc>""", tmpl.generate().render(encoding=None))
562 566
563 def test_without_strip(self): 567 def test_without_strip(self):
564 """ 568 """
565 Verify that a match template can produce the same kind of element that 569 Verify that a match template can produce the same kind of element that
566 it matched without entering an infinite recursion. 570 it matched without entering an infinite recursion.
573 </doc>""") 577 </doc>""")
574 self.assertEqual("""<doc> 578 self.assertEqual("""<doc>
575 <elem> 579 <elem>
576 <div class="elem">Hey Joe</div> 580 <div class="elem">Hey Joe</div>
577 </elem> 581 </elem>
578 </doc>""", str(tmpl.generate())) 582 </doc>""", tmpl.generate().render(encoding=None))
579 583
580 def test_as_element(self): 584 def test_as_element(self):
581 """ 585 """
582 Verify that the directive can also be used as an element. 586 Verify that the directive can also be used as an element.
583 """ 587 """
587 </py:match> 591 </py:match>
588 <elem>Hey Joe</elem> 592 <elem>Hey Joe</elem>
589 </doc>""") 593 </doc>""")
590 self.assertEqual("""<doc> 594 self.assertEqual("""<doc>
591 <div class="elem">Hey Joe</div> 595 <div class="elem">Hey Joe</div>
592 </doc>""", str(tmpl.generate())) 596 </doc>""", tmpl.generate().render(encoding=None))
593 597
594 def test_recursive_match_1(self): 598 def test_recursive_match_1(self):
595 """ 599 """
596 Match directives are applied recursively, meaning that they are also 600 Match directives are applied recursively, meaning that they are also
597 applied to any content they may have produced themselves: 601 applied to any content they may have produced themselves:
617 </div> 621 </div>
618 </elem> 622 </elem>
619 </subelem> 623 </subelem>
620 </div> 624 </div>
621 </elem> 625 </elem>
622 </doc>""", str(tmpl.generate())) 626 </doc>""", tmpl.generate().render(encoding=None))
623 627
624 def test_recursive_match_2(self): 628 def test_recursive_match_2(self):
625 """ 629 """
626 When two or more match templates match the same element and also 630 When two or more match templates match the same element and also
627 themselves output the element they match, avoiding recursion is even 631 themselves output the element they match, avoiding recursion is even
643 self.assertEqual("""<html> 647 self.assertEqual("""<html>
644 <body> 648 <body>
645 <div id="header"/><h1>Foo</h1> 649 <div id="header"/><h1>Foo</h1>
646 <div id="footer"/> 650 <div id="footer"/>
647 </body> 651 </body>
648 </html>""", str(tmpl.generate())) 652 </html>""", tmpl.generate().render(encoding=None))
649 653
650 def test_recursive_match_3(self): 654 def test_recursive_match_3(self):
651 tmpl = MarkupTemplate("""<test xmlns:py="http://genshi.edgewall.org/"> 655 tmpl = MarkupTemplate("""<test xmlns:py="http://genshi.edgewall.org/">
652 <py:match path="b[@type='bullet']"> 656 <py:match path="b[@type='bullet']">
653 <bullet>${select('*|text()')}</bullet> 657 <bullet>${select('*|text()')}</bullet>
669 """) 673 """)
670 self.assertEqual("""<test> 674 self.assertEqual("""<test>
671 <generic> 675 <generic>
672 <ul><bullet>1</bullet><bullet>2</bullet></ul> 676 <ul><bullet>1</bullet><bullet>2</bullet></ul>
673 </generic> 677 </generic>
674 </test>""", str(tmpl.generate())) 678 </test>""", tmpl.generate().render(encoding=None))
675 679
676 def test_not_match_self(self): 680 def test_not_match_self(self):
677 """ 681 """
678 See http://genshi.edgewall.org/ticket/77 682 See http://genshi.edgewall.org/ticket/77
679 """ 683 """
691 self.assertEqual("""<html xmlns="http://www.w3.org/1999/xhtml"> 695 self.assertEqual("""<html xmlns="http://www.w3.org/1999/xhtml">
692 <body><h1> 696 <body><h1>
693 Hello! 697 Hello!
694 Goodbye! 698 Goodbye!
695 </h1></body> 699 </h1></body>
696 </html>""", str(tmpl.generate())) 700 </html>""", tmpl.generate().render(encoding=None))
697 701
698 def test_select_text_in_element(self): 702 def test_select_text_in_element(self):
699 """ 703 """
700 See http://genshi.edgewall.org/ticket/77#comment:1 704 See http://genshi.edgewall.org/ticket/77#comment:1
701 """ 705 """
717 <text> 721 <text>
718 Hello! 722 Hello!
719 </text> 723 </text>
720 Goodbye! 724 Goodbye!
721 </h1></body> 725 </h1></body>
722 </html>""", str(tmpl.generate())) 726 </html>""", tmpl.generate().render(encoding=None))
723 727
724 def test_select_all_attrs(self): 728 def test_select_all_attrs(self):
725 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/"> 729 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
726 <div py:match="elem" py:attrs="select('@*')"> 730 <div py:match="elem" py:attrs="select('@*')">
727 ${select('text()')} 731 ${select('text()')}
730 </doc>""") 734 </doc>""")
731 self.assertEqual("""<doc> 735 self.assertEqual("""<doc>
732 <div id="joe"> 736 <div id="joe">
733 Hey Joe 737 Hey Joe
734 </div> 738 </div>
735 </doc>""", str(tmpl.generate())) 739 </doc>""", tmpl.generate().render(encoding=None))
736 740
737 def test_select_all_attrs_empty(self): 741 def test_select_all_attrs_empty(self):
738 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/"> 742 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
739 <div py:match="elem" py:attrs="select('@*')"> 743 <div py:match="elem" py:attrs="select('@*')">
740 ${select('text()')} 744 ${select('text()')}
743 </doc>""") 747 </doc>""")
744 self.assertEqual("""<doc> 748 self.assertEqual("""<doc>
745 <div> 749 <div>
746 Hey Joe 750 Hey Joe
747 </div> 751 </div>
748 </doc>""", str(tmpl.generate())) 752 </doc>""", tmpl.generate().render(encoding=None))
749 753
750 def test_select_all_attrs_in_body(self): 754 def test_select_all_attrs_in_body(self):
751 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/"> 755 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
752 <div py:match="elem"> 756 <div py:match="elem">
753 Hey ${select('text()')} ${select('@*')} 757 Hey ${select('text()')} ${select('@*')}
756 </doc>""") 760 </doc>""")
757 self.assertEqual("""<doc> 761 self.assertEqual("""<doc>
758 <div> 762 <div>
759 Hey Joe Cool 763 Hey Joe Cool
760 </div> 764 </div>
761 </doc>""", str(tmpl.generate())) 765 </doc>""", tmpl.generate().render(encoding=None))
762 766
763 def test_def_in_match(self): 767 def test_def_in_match(self):
764 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/"> 768 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
765 <py:def function="maketitle(test)"><b py:replace="test" /></py:def> 769 <py:def function="maketitle(test)"><b py:replace="test" /></py:def>
766 <head py:match="head">${select('*')}</head> 770 <head py:match="head">${select('*')}</head>
767 <head><title>${maketitle(True)}</title></head> 771 <head><title>${maketitle(True)}</title></head>
768 </doc>""") 772 </doc>""")
769 self.assertEqual("""<doc> 773 self.assertEqual("""<doc>
770 <head><title>True</title></head> 774 <head><title>True</title></head>
771 </doc>""", str(tmpl.generate())) 775 </doc>""", tmpl.generate().render(encoding=None))
772 776
773 def test_match_with_xpath_variable(self): 777 def test_match_with_xpath_variable(self):
774 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 778 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
775 <span py:match="*[name()=$tagname]"> 779 <span py:match="*[name()=$tagname]">
776 Hello ${select('@name')} 780 Hello ${select('@name')}
779 </div>""") 783 </div>""")
780 self.assertEqual("""<div> 784 self.assertEqual("""<div>
781 <span> 785 <span>
782 Hello Dude 786 Hello Dude
783 </span> 787 </span>
784 </div>""", str(tmpl.generate(tagname='greeting'))) 788 </div>""", tmpl.generate(tagname='greeting').render(encoding=None))
785 self.assertEqual("""<div> 789 self.assertEqual("""<div>
786 <greeting name="Dude"/> 790 <greeting name="Dude"/>
787 </div>""", str(tmpl.generate(tagname='sayhello'))) 791 </div>""", tmpl.generate(tagname='sayhello').render(encoding=None))
788 792
789 def test_content_directive_in_match(self): 793 def test_content_directive_in_match(self):
790 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> 794 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
791 <div py:match="foo">I said <q py:content="select('text()')">something</q>.</div> 795 <div py:match="foo">I said <q py:content="select('text()')">something</q>.</div>
792 <foo>bar</foo> 796 <foo>bar</foo>
793 </html>""") 797 </html>""")
794 self.assertEqual("""<html> 798 self.assertEqual("""<html>
795 <div>I said <q>bar</q>.</div> 799 <div>I said <q>bar</q>.</div>
796 </html>""", str(tmpl.generate())) 800 </html>""", tmpl.generate().render(encoding=None))
797 801
798 def test_cascaded_matches(self): 802 def test_cascaded_matches(self):
799 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> 803 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
800 <body py:match="body">${select('*')}</body> 804 <body py:match="body">${select('*')}</body>
801 <head py:match="head">${select('title')}</head> 805 <head py:match="head">${select('title')}</head>
804 <body><h2>Are you ready to mark up?</h2></body> 808 <body><h2>Are you ready to mark up?</h2></body>
805 </html>""") 809 </html>""")
806 self.assertEqual("""<html> 810 self.assertEqual("""<html>
807 <head><title>Welcome to Markup</title></head> 811 <head><title>Welcome to Markup</title></head>
808 <body><h2>Are you ready to mark up?</h2><hr/></body> 812 <body><h2>Are you ready to mark up?</h2><hr/></body>
809 </html>""", str(tmpl.generate())) 813 </html>""", tmpl.generate().render(encoding=None))
810 814
811 def test_multiple_matches(self): 815 def test_multiple_matches(self):
812 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> 816 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
813 <input py:match="form//input" py:attrs="select('@*')" 817 <input py:match="form//input" py:attrs="select('@*')"
814 value="${values[str(select('@name'))]}" /> 818 value="${values[str(select('@name'))]}" />
834 <input value="3" type="text" name="hello_3"/> 838 <input value="3" type="text" name="hello_3"/>
835 </p><p> 839 </p><p>
836 <label>Hello_4</label> 840 <label>Hello_4</label>
837 <input value="4" type="text" name="hello_4"/> 841 <input value="4" type="text" name="hello_4"/>
838 </p></form> 842 </p></form>
839 </html>""", str(tmpl.generate(fields=fields, values=values))) 843 </html>""", tmpl.generate(fields=fields, values=values)
844 .render(encoding=None))
840 845
841 def test_namespace_context(self): 846 def test_namespace_context(self):
842 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 847 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"
843 xmlns:x="http://www.example.org/"> 848 xmlns:x="http://www.example.org/">
844 <div py:match="x:foo">Foo</div> 849 <div py:match="x:foo">Foo</div>
846 </html>""") 851 </html>""")
847 # FIXME: there should be a way to strip out unwanted/unused namespaces, 852 # FIXME: there should be a way to strip out unwanted/unused namespaces,
848 # such as the "x" in this example 853 # such as the "x" in this example
849 self.assertEqual("""<html xmlns:x="http://www.example.org/"> 854 self.assertEqual("""<html xmlns:x="http://www.example.org/">
850 <div>Foo</div> 855 <div>Foo</div>
851 </html>""", str(tmpl.generate())) 856 </html>""", tmpl.generate().render(encoding=None))
852 857
853 def test_match_with_position_predicate(self): 858 def test_match_with_position_predicate(self):
854 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> 859 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
855 <p py:match="body/p[1]" class="first">${select('*|text()')}</p> 860 <p py:match="body/p[1]" class="first">${select('*|text()')}</p>
856 <body> 861 <body>
861 self.assertEqual("""<html> 866 self.assertEqual("""<html>
862 <body> 867 <body>
863 <p class="first">Foo</p> 868 <p class="first">Foo</p>
864 <p>Bar</p> 869 <p>Bar</p>
865 </body> 870 </body>
866 </html>""", str(tmpl.generate())) 871 </html>""", tmpl.generate().render(encoding=None))
867 872
868 def test_match_with_closure(self): 873 def test_match_with_closure(self):
869 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> 874 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
870 <p py:match="body//p" class="para">${select('*|text()')}</p> 875 <p py:match="body//p" class="para">${select('*|text()')}</p>
871 <body> 876 <body>
876 self.assertEqual("""<html> 881 self.assertEqual("""<html>
877 <body> 882 <body>
878 <p class="para">Foo</p> 883 <p class="para">Foo</p>
879 <div><p class="para">Bar</p></div> 884 <div><p class="para">Bar</p></div>
880 </body> 885 </body>
881 </html>""", str(tmpl.generate())) 886 </html>""", tmpl.generate().render(encoding=None))
882 887
883 def test_match_without_closure(self): 888 def test_match_without_closure(self):
884 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> 889 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
885 <p py:match="body/p" class="para">${select('*|text()')}</p> 890 <p py:match="body/p" class="para">${select('*|text()')}</p>
886 <body> 891 <body>
891 self.assertEqual("""<html> 896 self.assertEqual("""<html>
892 <body> 897 <body>
893 <p class="para">Foo</p> 898 <p class="para">Foo</p>
894 <div><p>Bar</p></div> 899 <div><p>Bar</p></div>
895 </body> 900 </body>
896 </html>""", str(tmpl.generate())) 901 </html>""", tmpl.generate().render(encoding=None))
897 902
898 def test_match_with_once_attribute(self): 903 def test_match_with_once_attribute(self):
899 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> 904 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
900 <py:match path="body" once="true"><body> 905 <py:match path="body" once="true"><body>
901 <div id="wrap"> 906 <div id="wrap">
916 </div> 921 </div>
917 </body> 922 </body>
918 <body> 923 <body>
919 <p>Bar</p> 924 <p>Bar</p>
920 </body> 925 </body>
921 </html>""", str(tmpl.generate())) 926 </html>""", tmpl.generate().render(encoding=None))
922 927
923 def test_match_with_recursive_attribute(self): 928 def test_match_with_recursive_attribute(self):
924 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/"> 929 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
925 <py:match path="elem" recursive="false"><elem> 930 <py:match path="elem" recursive="false"><elem>
926 <div class="elem"> 931 <div class="elem">
939 <subelem> 944 <subelem>
940 <elem/> 945 <elem/>
941 </subelem> 946 </subelem>
942 </div> 947 </div>
943 </elem> 948 </elem>
944 </doc>""", str(tmpl.generate())) 949 </doc>""", tmpl.generate().render(encoding=None))
950
951 # See http://genshi.edgewall.org/ticket/254/
952 def test_triple_match_produces_no_duplicate_items(self):
953 tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
954 <div py:match="div[@id='content']" py:attrs="select('@*')" once="true">
955 <ul id="tabbed_pane" />
956 ${select('*')}
957 </div>
958
959 <body py:match="body" once="true" buffer="false">
960 ${select('*|text()')}
961 </body>
962 <body py:match="body" once="true" buffer="false">
963 ${select('*|text()')}
964 </body>
965
966 <body>
967 <div id="content">
968 <h1>Ticket X</h1>
969 </div>
970 </body>
971 </doc>""")
972 output = tmpl.generate().render('xhtml', doctype='xhtml')
973 matches = re.findall("tabbed_pane", output)
974 self.assertNotEqual(None, matches)
975 self.assertEqual(1, len(matches))
976
977 def test_match_multiple_times1(self):
978 # See http://genshi.edgewall.org/ticket/370
979 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
980 <py:match path="body[@id='content']/h2" />
981 <head py:match="head" />
982 <head py:match="head" />
983 <head />
984 <body />
985 </html>""")
986 self.assertEqual("""<html>
987 <head/>
988 <body/>
989 </html>""", tmpl.generate().render())
990
991 def test_match_multiple_times2(self):
992 # See http://genshi.edgewall.org/ticket/370
993 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
994 <py:match path="body/div[@id='properties']" />
995 <head py:match="head" />
996 <head py:match="head" />
997 <head/>
998 <body>
999 <div id="properties">Foo</div>
1000 </body>
1001 </html>""")
1002 self.assertEqual("""<html>
1003 <head/>
1004 <body>
1005 </body>
1006 </html>""", tmpl.generate().render())
945 1007
946 # FIXME 1008 # FIXME
947 #def test_match_after_step(self): 1009 #def test_match_after_step(self):
948 # tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 1010 # tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
949 # <span py:match="div/greeting"> 1011 # <span py:match="div/greeting">
953 # </div>""") 1015 # </div>""")
954 # self.assertEqual("""<div> 1016 # self.assertEqual("""<div>
955 # <span> 1017 # <span>
956 # Hello Dude 1018 # Hello Dude
957 # </span> 1019 # </span>
958 # </div>""", str(tmpl.generate())) 1020 # </div>""", tmpl.generate().render(encoding=None))
959 1021
960 1022
961 class ContentDirectiveTestCase(unittest.TestCase): 1023 class ContentDirectiveTestCase(unittest.TestCase):
962 """Tests for the `py:content` template directive.""" 1024 """Tests for the `py:content` template directive."""
963 1025
993 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 1055 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
994 <py:replace value="title" /> 1056 <py:replace value="title" />
995 </div>""", filename='test.html') 1057 </div>""", filename='test.html')
996 self.assertEqual("""<div> 1058 self.assertEqual("""<div>
997 Test 1059 Test
998 </div>""", str(tmpl.generate(title='Test'))) 1060 </div>""", tmpl.generate(title='Test').render(encoding=None))
999 1061
1000 1062
1001 class StripDirectiveTestCase(unittest.TestCase): 1063 class StripDirectiveTestCase(unittest.TestCase):
1002 """Tests for the `py:strip` template directive.""" 1064 """Tests for the `py:strip` template directive."""
1003 1065
1005 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 1067 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1006 <div py:strip="False"><b>foo</b></div> 1068 <div py:strip="False"><b>foo</b></div>
1007 </div>""") 1069 </div>""")
1008 self.assertEqual("""<div> 1070 self.assertEqual("""<div>
1009 <div><b>foo</b></div> 1071 <div><b>foo</b></div>
1010 </div>""", str(tmpl.generate())) 1072 </div>""", tmpl.generate().render(encoding=None))
1011 1073
1012 def test_strip_empty(self): 1074 def test_strip_empty(self):
1013 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 1075 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1014 <div py:strip=""><b>foo</b></div> 1076 <div py:strip=""><b>foo</b></div>
1015 </div>""") 1077 </div>""")
1016 self.assertEqual("""<div> 1078 self.assertEqual("""<div>
1017 <b>foo</b> 1079 <b>foo</b>
1018 </div>""", str(tmpl.generate())) 1080 </div>""", tmpl.generate().render(encoding=None))
1019 1081
1020 1082
1021 class WithDirectiveTestCase(unittest.TestCase): 1083 class WithDirectiveTestCase(unittest.TestCase):
1022 """Tests for the `py:with` template directive.""" 1084 """Tests for the `py:with` template directive."""
1023 1085
1029 </div>""") 1091 </div>""")
1030 self.assertEqual("""<div> 1092 self.assertEqual("""<div>
1031 42 1093 42
1032 84 1094 84
1033 42 1095 42
1034 </div>""", str(tmpl.generate(x=42))) 1096 </div>""", tmpl.generate(x=42).render(encoding=None))
1035 1097
1036 def test_as_element(self): 1098 def test_as_element(self):
1037 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 1099 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1038 <py:with vars="x = x * 2">${x}</py:with> 1100 <py:with vars="x = x * 2">${x}</py:with>
1039 </div>""") 1101 </div>""")
1040 self.assertEqual("""<div> 1102 self.assertEqual("""<div>
1041 84 1103 84
1042 </div>""", str(tmpl.generate(x=42))) 1104 </div>""", tmpl.generate(x=42).render(encoding=None))
1043 1105
1044 def test_multiple_vars_same_name(self): 1106 def test_multiple_vars_same_name(self):
1045 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 1107 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1046 <py:with vars=" 1108 <py:with vars="
1047 foo = 'bar'; 1109 foo = 'bar';
1050 $foo 1112 $foo
1051 </py:with> 1113 </py:with>
1052 </div>""") 1114 </div>""")
1053 self.assertEqual("""<div> 1115 self.assertEqual("""<div>
1054 baz 1116 baz
1055 </div>""", str(tmpl.generate(x=42))) 1117 </div>""", tmpl.generate(x=42).render(encoding=None))
1056 1118
1057 def test_multiple_vars_single_assignment(self): 1119 def test_multiple_vars_single_assignment(self):
1058 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 1120 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1059 <py:with vars="x = y = z = 1">${x} ${y} ${z}</py:with> 1121 <py:with vars="x = y = z = 1">${x} ${y} ${z}</py:with>
1060 </div>""") 1122 </div>""")
1061 self.assertEqual("""<div> 1123 self.assertEqual("""<div>
1062 1 1 1 1124 1 1 1
1063 </div>""", str(tmpl.generate(x=42))) 1125 </div>""", tmpl.generate(x=42).render(encoding=None))
1064 1126
1065 def test_nested_vars_single_assignment(self): 1127 def test_nested_vars_single_assignment(self):
1066 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 1128 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1067 <py:with vars="x, (y, z) = (1, (2, 3))">${x} ${y} ${z}</py:with> 1129 <py:with vars="x, (y, z) = (1, (2, 3))">${x} ${y} ${z}</py:with>
1068 </div>""") 1130 </div>""")
1069 self.assertEqual("""<div> 1131 self.assertEqual("""<div>
1070 1 2 3 1132 1 2 3
1071 </div>""", str(tmpl.generate(x=42))) 1133 </div>""", tmpl.generate(x=42).render(encoding=None))
1072 1134
1073 def test_multiple_vars_trailing_semicolon(self): 1135 def test_multiple_vars_trailing_semicolon(self):
1074 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 1136 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1075 <py:with vars="x = x * 2; y = x / 2;">${x} ${y}</py:with> 1137 <py:with vars="x = x * 2; y = x / 2;">${x} ${y}</py:with>
1076 </div>""") 1138 </div>""")
1077 self.assertEqual("""<div> 1139 self.assertEqual("""<div>
1078 84 42 1140 84 42
1079 </div>""", str(tmpl.generate(x=42))) 1141 </div>""", tmpl.generate(x=42).render(encoding=None))
1080 1142
1081 def test_semicolon_escape(self): 1143 def test_semicolon_escape(self):
1082 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 1144 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1083 <py:with vars="x = 'here is a semicolon: ;'; y = 'here are two semicolons: ;;' ;"> 1145 <py:with vars="x = 'here is a semicolon: ;'; y = 'here are two semicolons: ;;' ;">
1084 ${x} 1146 ${x}
1086 </py:with> 1148 </py:with>
1087 </div>""") 1149 </div>""")
1088 self.assertEqual("""<div> 1150 self.assertEqual("""<div>
1089 here is a semicolon: ; 1151 here is a semicolon: ;
1090 here are two semicolons: ;; 1152 here are two semicolons: ;;
1091 </div>""", str(tmpl.generate())) 1153 </div>""", tmpl.generate().render(encoding=None))
1092 1154
1093 def test_ast_transformation(self): 1155 def test_ast_transformation(self):
1094 """ 1156 """
1095 Verify that the usual template expression AST transformations are 1157 Verify that the usual template expression AST transformations are
1096 applied despite the code being compiled to a `Suite` object. 1158 applied despite the code being compiled to a `Suite` object.
1102 </div>""") 1164 </div>""")
1103 self.assertEqual("""<div> 1165 self.assertEqual("""<div>
1104 <span> 1166 <span>
1105 42 1167 42
1106 </span> 1168 </span>
1107 </div>""", str(tmpl.generate(foo={'bar': 42}))) 1169 </div>""", tmpl.generate(foo={'bar': 42}).render(encoding=None))
1108 1170
1109 def test_unicode_expr(self): 1171 def test_unicode_expr(self):
1110 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 1172 tmpl = MarkupTemplate(u"""<div xmlns:py="http://genshi.edgewall.org/">
1111 <span py:with="weeks=(u'一', u'二', u'三', u'四', u'五', u'六', u'日')"> 1173 <span py:with="weeks=(u'一', u'二', u'三', u'四', u'五', u'六', u'日')">
1112 $weeks 1174 $weeks
1113 </span> 1175 </span>
1114 </div>""") 1176 </div>""")
1115 self.assertEqual("""<div> 1177 self.assertEqual(u"""<div>
1116 <span> 1178 <span>
1117 一二三四五六日 1179 一二三四五六日
1118 </span> 1180 </span>
1119 </div>""", str(tmpl.generate())) 1181 </div>""", tmpl.generate().render(encoding=None))
1120 1182
1121 def test_with_empty_value(self): 1183 def test_with_empty_value(self):
1122 """ 1184 """
1123 Verify that an empty py:with works (useless, but legal) 1185 Verify that an empty py:with works (useless, but legal)
1124 """ 1186 """
1125 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/"> 1187 tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1126 <span py:with="">Text</span></div>""") 1188 <span py:with="">Text</span></div>""")
1127 1189
1128 self.assertEqual("""<div> 1190 self.assertEqual("""<div>
1129 <span>Text</span></div>""", str(tmpl.generate())) 1191 <span>Text</span></div>""", tmpl.generate().render(encoding=None))
1130 1192
1131 1193
1132 def suite(): 1194 def suite():
1133 suite = unittest.TestSuite() 1195 suite = unittest.TestSuite()
1134 suite.addTest(doctest.DocTestSuite(directives)) 1196 suite.addTest(doctest.DocTestSuite(directives))
Copyright (C) 2012-2017 Edgewall Software