~ubuntu-branches/ubuntu/raring/genshi/raring-proposed

« back to all changes in this revision

Viewing changes to genshi/tests/template.py

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Fontaine
  • Date: 2007-04-16 17:49:03 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070416174903-x2p3n9g890v18d0m
Tags: 0.4-1
* New upstream release.
* Remove useless python-markup transition package.
* Add Provides against python-markup.
* Add doc-base.
* Add depends against python-xml.
* Add suggests to python-setuptools.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
#
3
 
# Copyright (C) 2006 Edgewall Software
4
 
# All rights reserved.
5
 
#
6
 
# This software is licensed as described in the file COPYING, which
7
 
# you should have received as part of this distribution. The terms
8
 
# are also available at http://genshi.edgewall.org/wiki/License.
9
 
#
10
 
# This software consists of voluntary contributions made by many
11
 
# individuals. For the exact contribution history, see the revision
12
 
# history and logs, available at http://genshi.edgewall.org/log/.
13
 
 
14
 
import doctest
15
 
import os
16
 
import unittest
17
 
import shutil
18
 
import sys
19
 
import tempfile
20
 
 
21
 
from genshi import template
22
 
from genshi.core import Markup, Stream
23
 
from genshi.template import BadDirectiveError, MarkupTemplate, Template, \
24
 
                            TemplateLoader, TemplateRuntimeError, \
25
 
                            TemplateSyntaxError, TextTemplate
26
 
 
27
 
 
28
 
class AttrsDirectiveTestCase(unittest.TestCase):
29
 
    """Tests for the `py:attrs` template directive."""
30
 
 
31
 
    def test_combined_with_loop(self):
32
 
        """
33
 
        Verify that the directive has access to the loop variables.
34
 
        """
35
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
36
 
          <elem py:for="item in items" py:attrs="item"/>
37
 
        </doc>""")
38
 
        items = [{'id': 1, 'class': 'foo'}, {'id': 2, 'class': 'bar'}]
39
 
        self.assertEqual("""<doc>
40
 
          <elem id="1" class="foo"/><elem id="2" class="bar"/>
41
 
        </doc>""", str(tmpl.generate(items=items)))
42
 
 
43
 
    def test_update_existing_attr(self):
44
 
        """
45
 
        Verify that an attribute value that evaluates to `None` removes an
46
 
        existing attribute of that name.
47
 
        """
48
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
49
 
          <elem class="foo" py:attrs="{'class': 'bar'}"/>
50
 
        </doc>""")
51
 
        self.assertEqual("""<doc>
52
 
          <elem class="bar"/>
53
 
        </doc>""", str(tmpl.generate()))
54
 
 
55
 
    def test_remove_existing_attr(self):
56
 
        """
57
 
        Verify that an attribute value that evaluates to `None` removes an
58
 
        existing attribute of that name.
59
 
        """
60
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
61
 
          <elem class="foo" py:attrs="{'class': None}"/>
62
 
        </doc>""")
63
 
        self.assertEqual("""<doc>
64
 
          <elem/>
65
 
        </doc>""", str(tmpl.generate()))
66
 
 
67
 
 
68
 
class ChooseDirectiveTestCase(unittest.TestCase):
69
 
    """Tests for the `py:choose` template directive and the complementary
70
 
    directives `py:when` and `py:otherwise`."""
71
 
 
72
 
    def test_multiple_true_whens(self):
73
 
        """
74
 
        Verify that, if multiple `py:when` bodies match, only the first is
75
 
        output.
76
 
        """
77
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/" py:choose="">
78
 
          <span py:when="1 == 1">1</span>
79
 
          <span py:when="2 == 2">2</span>
80
 
          <span py:when="3 == 3">3</span>
81
 
        </div>""")
82
 
        self.assertEqual("""<div>
83
 
          <span>1</span>
84
 
        </div>""", str(tmpl.generate()))
85
 
 
86
 
    def test_otherwise(self):
87
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/" py:choose="">
88
 
          <span py:when="False">hidden</span>
89
 
          <span py:otherwise="">hello</span>
90
 
        </div>""")
91
 
        self.assertEqual("""<div>
92
 
          <span>hello</span>
93
 
        </div>""", str(tmpl.generate()))
94
 
 
95
 
    def test_nesting(self):
96
 
        """
97
 
        Verify that `py:choose` blocks can be nested:
98
 
        """
99
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
100
 
          <div py:choose="1">
101
 
            <div py:when="1" py:choose="3">
102
 
              <span py:when="2">2</span>
103
 
              <span py:when="3">3</span>
104
 
            </div>
105
 
          </div>
106
 
        </doc>""")
107
 
        self.assertEqual("""<doc>
108
 
          <div>
109
 
            <div>
110
 
              <span>3</span>
111
 
            </div>
112
 
          </div>
113
 
        </doc>""", str(tmpl.generate()))
114
 
 
115
 
    def test_complex_nesting(self):
116
 
        """
117
 
        Verify more complex nesting.
118
 
        """
119
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
120
 
          <div py:choose="1">
121
 
            <div py:when="1" py:choose="">
122
 
              <span py:when="2">OK</span>
123
 
              <span py:when="1">FAIL</span>
124
 
            </div>
125
 
          </div>
126
 
        </doc>""")
127
 
        self.assertEqual("""<doc>
128
 
          <div>
129
 
            <div>
130
 
              <span>OK</span>
131
 
            </div>
132
 
          </div>
133
 
        </doc>""", str(tmpl.generate()))
134
 
 
135
 
    def test_complex_nesting_otherwise(self):
136
 
        """
137
 
        Verify more complex nesting using otherwise.
138
 
        """
139
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
140
 
          <div py:choose="1">
141
 
            <div py:when="1" py:choose="2">
142
 
              <span py:when="1">FAIL</span>
143
 
              <span py:otherwise="">OK</span>
144
 
            </div>
145
 
          </div>
146
 
        </doc>""")
147
 
        self.assertEqual("""<doc>
148
 
          <div>
149
 
            <div>
150
 
              <span>OK</span>
151
 
            </div>
152
 
          </div>
153
 
        </doc>""", str(tmpl.generate()))
154
 
 
155
 
    def test_when_with_strip(self):
156
 
        """
157
 
        Verify that a when directive with a strip directive actually strips of
158
 
        the outer element.
159
 
        """
160
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
161
 
          <div py:choose="" py:strip="">
162
 
            <span py:otherwise="">foo</span>
163
 
          </div>
164
 
        </doc>""")
165
 
        self.assertEqual("""<doc>
166
 
            <span>foo</span>
167
 
        </doc>""", str(tmpl.generate()))
168
 
 
169
 
    def test_when_outside_choose(self):
170
 
        """
171
 
        Verify that a `when` directive outside of a `choose` directive is
172
 
        reported as an error.
173
 
        """
174
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
175
 
          <div py:when="xy" />
176
 
        </doc>""")
177
 
        self.assertRaises(TemplateRuntimeError, str, tmpl.generate())
178
 
 
179
 
    def test_otherwise_outside_choose(self):
180
 
        """
181
 
        Verify that an `otherwise` directive outside of a `choose` directive is
182
 
        reported as an error.
183
 
        """
184
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
185
 
          <div py:otherwise="" />
186
 
        </doc>""")
187
 
        self.assertRaises(TemplateRuntimeError, str, tmpl.generate())
188
 
 
189
 
    def test_when_without_test(self):
190
 
        """
191
 
        Verify that an `when` directive that doesn't have a `test` attribute
192
 
        is reported as an error.
193
 
        """
194
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
195
 
          <div py:choose="" py:strip="">
196
 
            <py:when>foo</py:when>
197
 
          </div>
198
 
        </doc>""")
199
 
        self.assertRaises(TemplateRuntimeError, str, tmpl.generate())
200
 
 
201
 
    def test_otherwise_without_test(self):
202
 
        """
203
 
        Verify that an `otherwise` directive can be used without a `test`
204
 
        attribute.
205
 
        """
206
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
207
 
          <div py:choose="" py:strip="">
208
 
            <py:otherwise>foo</py:otherwise>
209
 
          </div>
210
 
        </doc>""")
211
 
        self.assertEqual("""<doc>
212
 
            foo
213
 
        </doc>""", str(tmpl.generate()))
214
 
 
215
 
    def test_as_element(self):
216
 
        """
217
 
        Verify that the directive can also be used as an element.
218
 
        """
219
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
220
 
          <py:choose>
221
 
            <py:when test="1 == 1">1</py:when>
222
 
            <py:when test="2 == 2">2</py:when>
223
 
            <py:when test="3 == 3">3</py:when>
224
 
          </py:choose>
225
 
        </doc>""")
226
 
        self.assertEqual("""<doc>
227
 
            1
228
 
        </doc>""", str(tmpl.generate()))
229
 
 
230
 
    def test_in_text_template(self):
231
 
        """
232
 
        Verify that the directive works as expected in a text template.
233
 
        """
234
 
        tmpl = TextTemplate("""#choose
235
 
          #when 1 == 1
236
 
            1
237
 
          #end
238
 
          #when 2 == 2
239
 
            2
240
 
          #end
241
 
          #when 3 == 3
242
 
            3
243
 
          #end
244
 
        #end""")
245
 
        self.assertEqual("""            1\n""", str(tmpl.generate()))
246
 
 
247
 
 
248
 
class DefDirectiveTestCase(unittest.TestCase):
249
 
    """Tests for the `py:def` template directive."""
250
 
 
251
 
    def test_function_with_strip(self):
252
 
        """
253
 
        Verify that a named template function with a strip directive actually
254
 
        strips of the outer element.
255
 
        """
256
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
257
 
          <div py:def="echo(what)" py:strip="">
258
 
            <b>${what}</b>
259
 
          </div>
260
 
          ${echo('foo')}
261
 
        </doc>""")
262
 
        self.assertEqual("""<doc>
263
 
            <b>foo</b>
264
 
        </doc>""", str(tmpl.generate()))
265
 
 
266
 
    def test_exec_in_replace(self):
267
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
268
 
          <p py:def="echo(greeting, name='world')" class="message">
269
 
            ${greeting}, ${name}!
270
 
          </p>
271
 
          <div py:replace="echo('hello')"></div>
272
 
        </div>""")
273
 
        self.assertEqual("""<div>
274
 
          <p class="message">
275
 
            hello, world!
276
 
          </p>
277
 
        </div>""", str(tmpl.generate()))
278
 
 
279
 
    def test_as_element(self):
280
 
        """
281
 
        Verify that the directive can also be used as an element.
282
 
        """
283
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
284
 
          <py:def function="echo(what)">
285
 
            <b>${what}</b>
286
 
          </py:def>
287
 
          ${echo('foo')}
288
 
        </doc>""")
289
 
        self.assertEqual("""<doc>
290
 
            <b>foo</b>
291
 
        </doc>""", str(tmpl.generate()))
292
 
 
293
 
    def test_nested_defs(self):
294
 
        """
295
 
        Verify that a template function defined inside a conditional block can
296
 
        be called from outside that block.
297
 
        """
298
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
299
 
          <py:if test="semantic">
300
 
            <strong py:def="echo(what)">${what}</strong>
301
 
          </py:if>
302
 
          <py:if test="not semantic">
303
 
            <b py:def="echo(what)">${what}</b>
304
 
          </py:if>
305
 
          ${echo('foo')}
306
 
        </doc>""")
307
 
        self.assertEqual("""<doc>
308
 
          <strong>foo</strong>
309
 
        </doc>""", str(tmpl.generate(semantic=True)))
310
 
 
311
 
    def test_function_with_default_arg(self):
312
 
        """
313
 
        Verify that keyword arguments work with `py:def` directives.
314
 
        """
315
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
316
 
          <b py:def="echo(what, bold=False)" py:strip="not bold">${what}</b>
317
 
          ${echo('foo')}
318
 
        </doc>""")
319
 
        self.assertEqual("""<doc>
320
 
          foo
321
 
        </doc>""", str(tmpl.generate()))
322
 
 
323
 
    def test_invocation_in_attribute(self):
324
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
325
 
          <py:def function="echo(what)">${what or 'something'}</py:def>
326
 
          <p class="${echo('foo')}">bar</p>
327
 
        </doc>""")
328
 
        self.assertEqual("""<doc>
329
 
          <p class="foo">bar</p>
330
 
        </doc>""", str(tmpl.generate()))
331
 
 
332
 
    def test_invocation_in_attribute_none(self):
333
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
334
 
          <py:def function="echo()">${None}</py:def>
335
 
          <p class="${echo()}">bar</p>
336
 
        </doc>""")
337
 
        self.assertEqual("""<doc>
338
 
          <p>bar</p>
339
 
        </doc>""", str(tmpl.generate()))
340
 
 
341
 
    def test_function_raising_typeerror(self):
342
 
        def badfunc():
343
 
            raise TypeError
344
 
        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
345
 
          <div py:def="dobadfunc()">
346
 
            ${badfunc()}
347
 
          </div>
348
 
          <div py:content="dobadfunc()"/>
349
 
        </html>""")
350
 
        self.assertRaises(TypeError, list, tmpl.generate(badfunc=badfunc))
351
 
 
352
 
    def test_def_in_matched(self):
353
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
354
 
          <head py:match="head">${select('*')}</head>
355
 
          <head>
356
 
            <py:def function="maketitle(test)"><b py:replace="test" /></py:def>
357
 
            <title>${maketitle(True)}</title>
358
 
          </head>
359
 
        </doc>""")
360
 
        self.assertEqual("""<doc>
361
 
          <head><title>True</title></head>
362
 
        </doc>""", str(tmpl.generate()))
363
 
 
364
 
    def test_in_text_template(self):
365
 
        """
366
 
        Verify that the directive works as expected in a text template.
367
 
        """
368
 
        tmpl = TextTemplate("""
369
 
          #def echo(greeting, name='world')
370
 
            ${greeting}, ${name}!
371
 
          #end
372
 
          ${echo('Hi', name='you')}
373
 
        """)
374
 
        self.assertEqual("""
375
 
                      Hi, you!
376
 
        """, str(tmpl.generate()))
377
 
 
378
 
 
379
 
class ForDirectiveTestCase(unittest.TestCase):
380
 
    """Tests for the `py:for` template directive."""
381
 
 
382
 
    def test_loop_with_strip(self):
383
 
        """
384
 
        Verify that the combining the `py:for` directive with `py:strip` works
385
 
        correctly.
386
 
        """
387
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
388
 
          <div py:for="item in items" py:strip="">
389
 
            <b>${item}</b>
390
 
          </div>
391
 
        </doc>""")
392
 
        self.assertEqual("""<doc>
393
 
            <b>1</b>
394
 
            <b>2</b>
395
 
            <b>3</b>
396
 
            <b>4</b>
397
 
            <b>5</b>
398
 
        </doc>""", str(tmpl.generate(items=range(1, 6))))
399
 
 
400
 
    def test_as_element(self):
401
 
        """
402
 
        Verify that the directive can also be used as an element.
403
 
        """
404
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
405
 
          <py:for each="item in items">
406
 
            <b>${item}</b>
407
 
          </py:for>
408
 
        </doc>""")
409
 
        self.assertEqual("""<doc>
410
 
            <b>1</b>
411
 
            <b>2</b>
412
 
            <b>3</b>
413
 
            <b>4</b>
414
 
            <b>5</b>
415
 
        </doc>""", str(tmpl.generate(items=range(1, 6))))
416
 
 
417
 
    def test_multi_assignment(self):
418
 
        """
419
 
        Verify that assignment to tuples works correctly.
420
 
        """
421
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
422
 
          <py:for each="k, v in items">
423
 
            <p>key=$k, value=$v</p>
424
 
          </py:for>
425
 
        </doc>""")
426
 
        self.assertEqual("""<doc>
427
 
            <p>key=a, value=1</p>
428
 
            <p>key=b, value=2</p>
429
 
        </doc>""", str(tmpl.generate(items=dict(a=1, b=2).items())))
430
 
 
431
 
    def test_nested_assignment(self):
432
 
        """
433
 
        Verify that assignment to nested tuples works correctly.
434
 
        """
435
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
436
 
          <py:for each="idx, (k, v) in items">
437
 
            <p>$idx: key=$k, value=$v</p>
438
 
          </py:for>
439
 
        </doc>""")
440
 
        self.assertEqual("""<doc>
441
 
            <p>0: key=a, value=1</p>
442
 
            <p>1: key=b, value=2</p>
443
 
        </doc>""", str(tmpl.generate(items=enumerate(dict(a=1, b=2).items()))))
444
 
 
445
 
    def test_not_iterable(self):
446
 
        """
447
 
        Verify that assignment to nested tuples works correctly.
448
 
        """
449
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
450
 
          <py:for each="item in foo">
451
 
            $item
452
 
          </py:for>
453
 
        </doc>""", filename='test.html')
454
 
        try:
455
 
            list(tmpl.generate(foo=12))
456
 
        except TemplateRuntimeError, e:
457
 
            self.assertEqual('test.html', e.filename)
458
 
            if sys.version_info[:2] >= (2, 4):
459
 
                self.assertEqual(2, e.lineno)
460
 
 
461
 
 
462
 
class IfDirectiveTestCase(unittest.TestCase):
463
 
    """Tests for the `py:if` template directive."""
464
 
 
465
 
    def test_loop_with_strip(self):
466
 
        """
467
 
        Verify that the combining the `py:if` directive with `py:strip` works
468
 
        correctly.
469
 
        """
470
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
471
 
          <b py:if="foo" py:strip="">${bar}</b>
472
 
        </doc>""")
473
 
        self.assertEqual("""<doc>
474
 
          Hello
475
 
        </doc>""", str(tmpl.generate(foo=True, bar='Hello')))
476
 
 
477
 
    def test_as_element(self):
478
 
        """
479
 
        Verify that the directive can also be used as an element.
480
 
        """
481
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
482
 
          <py:if test="foo">${bar}</py:if>
483
 
        </doc>""")
484
 
        self.assertEqual("""<doc>
485
 
          Hello
486
 
        </doc>""", str(tmpl.generate(foo=True, bar='Hello')))
487
 
 
488
 
 
489
 
class MatchDirectiveTestCase(unittest.TestCase):
490
 
    """Tests for the `py:match` template directive."""
491
 
 
492
 
    def test_with_strip(self):
493
 
        """
494
 
        Verify that a match template can produce the same kind of element that
495
 
        it matched without entering an infinite recursion.
496
 
        """
497
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
498
 
          <elem py:match="elem" py:strip="">
499
 
            <div class="elem">${select('text()')}</div>
500
 
          </elem>
501
 
          <elem>Hey Joe</elem>
502
 
        </doc>""")
503
 
        self.assertEqual("""<doc>
504
 
            <div class="elem">Hey Joe</div>
505
 
        </doc>""", str(tmpl.generate()))
506
 
 
507
 
    def test_without_strip(self):
508
 
        """
509
 
        Verify that a match template can produce the same kind of element that
510
 
        it matched without entering an infinite recursion.
511
 
        """
512
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
513
 
          <elem py:match="elem">
514
 
            <div class="elem">${select('text()')}</div>
515
 
          </elem>
516
 
          <elem>Hey Joe</elem>
517
 
        </doc>""")
518
 
        self.assertEqual("""<doc>
519
 
          <elem>
520
 
            <div class="elem">Hey Joe</div>
521
 
          </elem>
522
 
        </doc>""", str(tmpl.generate()))
523
 
 
524
 
    def test_as_element(self):
525
 
        """
526
 
        Verify that the directive can also be used as an element.
527
 
        """
528
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
529
 
          <py:match path="elem">
530
 
            <div class="elem">${select('text()')}</div>
531
 
          </py:match>
532
 
          <elem>Hey Joe</elem>
533
 
        </doc>""")
534
 
        self.assertEqual("""<doc>
535
 
            <div class="elem">Hey Joe</div>
536
 
        </doc>""", str(tmpl.generate()))
537
 
 
538
 
    def test_recursive_match_1(self):
539
 
        """
540
 
        Match directives are applied recursively, meaning that they are also
541
 
        applied to any content they may have produced themselves:
542
 
        """
543
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
544
 
          <elem py:match="elem">
545
 
            <div class="elem">
546
 
              ${select('*')}
547
 
            </div>
548
 
          </elem>
549
 
          <elem>
550
 
            <subelem>
551
 
              <elem/>
552
 
            </subelem>
553
 
          </elem>
554
 
        </doc>""")
555
 
        self.assertEqual("""<doc>
556
 
          <elem>
557
 
            <div class="elem">
558
 
              <subelem>
559
 
              <elem>
560
 
            <div class="elem">
561
 
            </div>
562
 
          </elem>
563
 
            </subelem>
564
 
            </div>
565
 
          </elem>
566
 
        </doc>""", str(tmpl.generate()))
567
 
 
568
 
    def test_recursive_match_2(self):
569
 
        """
570
 
        When two or more match templates match the same element and also
571
 
        themselves output the element they match, avoiding recursion is even
572
 
        more complex, but should work.
573
 
        """
574
 
        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
575
 
          <body py:match="body">
576
 
            <div id="header"/>
577
 
            ${select('*')}
578
 
          </body>
579
 
          <body py:match="body">
580
 
            ${select('*')}
581
 
            <div id="footer"/>
582
 
          </body>
583
 
          <body>
584
 
            <h1>Foo</h1>
585
 
          </body>
586
 
        </html>""")
587
 
        self.assertEqual("""<html>
588
 
          <body>
589
 
            <div id="header"/><h1>Foo</h1>
590
 
            <div id="footer"/>
591
 
          </body>
592
 
        </html>""", str(tmpl.generate()))
593
 
 
594
 
    def test_not_match_self(self):
595
 
        """
596
 
        See http://genshi.edgewall.org/ticket/77
597
 
        """
598
 
        tmpl = MarkupTemplate("""<html xmlns="http://www.w3.org/1999/xhtml"
599
 
              xmlns:py="http://genshi.edgewall.org/">
600
 
          <body py:match="body" py:content="select('*')" />
601
 
          <h1 py:match="h1">
602
 
            ${select('text()')}
603
 
            Goodbye!
604
 
          </h1>
605
 
          <body>
606
 
            <h1>Hello!</h1>
607
 
          </body>
608
 
        </html>""")
609
 
        self.assertEqual("""<html xmlns="http://www.w3.org/1999/xhtml">
610
 
          <body><h1>
611
 
            Hello!
612
 
            Goodbye!
613
 
          </h1></body>
614
 
        </html>""", str(tmpl.generate()))
615
 
 
616
 
    def test_select_text_in_element(self):
617
 
        """
618
 
        See http://genshi.edgewall.org/ticket/77#comment:1
619
 
        """
620
 
        tmpl = MarkupTemplate("""<html xmlns="http://www.w3.org/1999/xhtml"
621
 
              xmlns:py="http://genshi.edgewall.org/">
622
 
          <body py:match="body" py:content="select('*')" />
623
 
          <h1 py:match="h1">
624
 
            <text>
625
 
              ${select('text()')}
626
 
            </text>
627
 
            Goodbye!
628
 
          </h1>
629
 
          <body>
630
 
            <h1>Hello!</h1>
631
 
          </body>
632
 
        </html>""")
633
 
        self.assertEqual("""<html xmlns="http://www.w3.org/1999/xhtml">
634
 
          <body><h1>
635
 
            <text>
636
 
              Hello!
637
 
            </text>
638
 
            Goodbye!
639
 
          </h1></body>
640
 
        </html>""", str(tmpl.generate()))
641
 
 
642
 
    def test_select_all_attrs(self):
643
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
644
 
          <div py:match="elem" py:attrs="select('@*')">
645
 
            ${select('text()')}
646
 
          </div>
647
 
          <elem id="joe">Hey Joe</elem>
648
 
        </doc>""")
649
 
        self.assertEqual("""<doc>
650
 
          <div id="joe">
651
 
            Hey Joe
652
 
          </div>
653
 
        </doc>""", str(tmpl.generate()))
654
 
 
655
 
    def test_select_all_attrs_empty(self):
656
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
657
 
          <div py:match="elem" py:attrs="select('@*')">
658
 
            ${select('text()')}
659
 
          </div>
660
 
          <elem>Hey Joe</elem>
661
 
        </doc>""")
662
 
        self.assertEqual("""<doc>
663
 
          <div>
664
 
            Hey Joe
665
 
          </div>
666
 
        </doc>""", str(tmpl.generate()))
667
 
 
668
 
    def test_select_all_attrs_in_body(self):
669
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
670
 
          <div py:match="elem">
671
 
            Hey ${select('text()')} ${select('@*')}
672
 
          </div>
673
 
          <elem title="Cool">Joe</elem>
674
 
        </doc>""")
675
 
        self.assertEqual("""<doc>
676
 
          <div>
677
 
            Hey Joe Cool
678
 
          </div>
679
 
        </doc>""", str(tmpl.generate()))
680
 
 
681
 
    def test_def_in_match(self):
682
 
        tmpl = MarkupTemplate("""<doc xmlns:py="http://genshi.edgewall.org/">
683
 
          <py:def function="maketitle(test)"><b py:replace="test" /></py:def>
684
 
          <head py:match="head">${select('*')}</head>
685
 
          <head><title>${maketitle(True)}</title></head>
686
 
        </doc>""")
687
 
        self.assertEqual("""<doc>
688
 
          <head><title>True</title></head>
689
 
        </doc>""", str(tmpl.generate()))
690
 
 
691
 
    def test_match_with_xpath_variable(self):
692
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
693
 
          <span py:match="*[name()=$tagname]">
694
 
            Hello ${select('@name')}
695
 
          </span>
696
 
          <greeting name="Dude"/>
697
 
        </div>""")
698
 
        self.assertEqual("""<div>
699
 
          <span>
700
 
            Hello Dude
701
 
          </span>
702
 
        </div>""", str(tmpl.generate(tagname='greeting')))
703
 
        self.assertEqual("""<div>
704
 
          <greeting name="Dude"/>
705
 
        </div>""", str(tmpl.generate(tagname='sayhello')))
706
 
 
707
 
    def test_content_directive_in_match(self):
708
 
        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
709
 
          <div py:match="foo">I said <q py:content="select('text()')">something</q>.</div>
710
 
          <foo>bar</foo>
711
 
        </html>""")
712
 
        self.assertEqual("""<html>
713
 
          <div>I said <q>bar</q>.</div>
714
 
        </html>""", str(tmpl.generate()))
715
 
 
716
 
    def test_cascaded_matches(self):
717
 
        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
718
 
          <body py:match="body">${select('*')}</body>
719
 
          <head py:match="head">${select('title')}</head>
720
 
          <body py:match="body">${select('*')}<hr /></body>
721
 
          <head><title>Welcome to Markup</title></head>
722
 
          <body><h2>Are you ready to mark up?</h2></body>
723
 
        </html>""")
724
 
        self.assertEqual("""<html>
725
 
          <head><title>Welcome to Markup</title></head>
726
 
          <body><h2>Are you ready to mark up?</h2><hr/></body>
727
 
        </html>""", str(tmpl.generate()))
728
 
 
729
 
    def test_multiple_matches(self):
730
 
        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
731
 
          <input py:match="form//input" py:attrs="select('@*')"
732
 
                 value="${values[str(select('@name'))]}" />
733
 
          <form><p py:for="field in fields">
734
 
            <label>${field.capitalize()}</label>
735
 
            <input type="text" name="${field}" />
736
 
          </p></form>
737
 
        </html>""")
738
 
        fields = ['hello_%s' % i for i in range(5)]
739
 
        values = dict([('hello_%s' % i, i) for i in range(5)])
740
 
        self.assertEqual("""<html>
741
 
          <form><p>
742
 
            <label>Hello_0</label>
743
 
            <input value="0" type="text" name="hello_0"/>
744
 
          </p><p>
745
 
            <label>Hello_1</label>
746
 
            <input value="1" type="text" name="hello_1"/>
747
 
          </p><p>
748
 
            <label>Hello_2</label>
749
 
            <input value="2" type="text" name="hello_2"/>
750
 
          </p><p>
751
 
            <label>Hello_3</label>
752
 
            <input value="3" type="text" name="hello_3"/>
753
 
          </p><p>
754
 
            <label>Hello_4</label>
755
 
            <input value="4" type="text" name="hello_4"/>
756
 
          </p></form>
757
 
        </html>""", str(tmpl.generate(fields=fields, values=values)))
758
 
 
759
 
    def test_namespace_context(self):
760
 
        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"
761
 
                                       xmlns:x="http://www.example.org/">
762
 
          <div py:match="x:foo">Foo</div>
763
 
          <foo xmlns="http://www.example.org/"/>
764
 
        </html>""")
765
 
        # FIXME: there should be a way to strip out unwanted/unused namespaces,
766
 
        #        such as the "x" in this example
767
 
        self.assertEqual("""<html xmlns:x="http://www.example.org/">
768
 
          <div>Foo</div>
769
 
        </html>""", str(tmpl.generate()))
770
 
 
771
 
    def test_match_without_closure(self):
772
 
        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/">
773
 
          <p py:match="body/p" class="para">${select('*|text()')}</p>
774
 
          <body>
775
 
            <p>Foo</p>
776
 
            <div><p>Bar</p></div>
777
 
          </body>
778
 
        </html>""")
779
 
        self.assertEqual("""<html>
780
 
          <body>
781
 
            <p class="para">Foo</p>
782
 
            <div><p>Bar</p></div>
783
 
          </body>
784
 
        </html>""", str(tmpl.generate()))
785
 
 
786
 
    # FIXME
787
 
    #def test_match_after_step(self):
788
 
    #    tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
789
 
    #      <span py:match="div/greeting">
790
 
    #        Hello ${select('@name')}
791
 
    #      </span>
792
 
    #      <greeting name="Dude" />
793
 
    #    </div>""")
794
 
    #    self.assertEqual("""<div>
795
 
    #      <span>
796
 
    #        Hello Dude
797
 
    #      </span>
798
 
    #    </div>""", str(tmpl.generate()))
799
 
 
800
 
 
801
 
class StripDirectiveTestCase(unittest.TestCase):
802
 
    """Tests for the `py:strip` template directive."""
803
 
 
804
 
    def test_strip_false(self):
805
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
806
 
          <div py:strip="False"><b>foo</b></div>
807
 
        </div>""")
808
 
        self.assertEqual("""<div>
809
 
          <div><b>foo</b></div>
810
 
        </div>""", str(tmpl.generate()))
811
 
 
812
 
    def test_strip_empty(self):
813
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
814
 
          <div py:strip=""><b>foo</b></div>
815
 
        </div>""")
816
 
        self.assertEqual("""<div>
817
 
          <b>foo</b>
818
 
        </div>""", str(tmpl.generate()))
819
 
 
820
 
 
821
 
class WithDirectiveTestCase(unittest.TestCase):
822
 
    """Tests for the `py:with` template directive."""
823
 
 
824
 
    def test_shadowing(self):
825
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
826
 
          ${x}
827
 
          <span py:with="x = x * 2" py:replace="x"/>
828
 
          ${x}
829
 
        </div>""")
830
 
        self.assertEqual("""<div>
831
 
          42
832
 
          84
833
 
          42
834
 
        </div>""", str(tmpl.generate(x=42)))
835
 
 
836
 
    def test_as_element(self):
837
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
838
 
          <py:with vars="x = x * 2">${x}</py:with>
839
 
        </div>""")
840
 
        self.assertEqual("""<div>
841
 
          84
842
 
        </div>""", str(tmpl.generate(x=42)))
843
 
 
844
 
    def test_multiple_vars_same_name(self):
845
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
846
 
          <py:with vars="
847
 
            foo = 'bar';
848
 
            foo = foo.replace('r', 'z')
849
 
          ">
850
 
            $foo
851
 
          </py:with>
852
 
        </div>""")
853
 
        self.assertEqual("""<div>
854
 
            baz
855
 
        </div>""", str(tmpl.generate(x=42)))
856
 
 
857
 
    def test_multiple_vars_single_assignment(self):
858
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
859
 
          <py:with vars="x = y = z = 1">${x} ${y} ${z}</py:with>
860
 
        </div>""")
861
 
        self.assertEqual("""<div>
862
 
          1 1 1
863
 
        </div>""", str(tmpl.generate(x=42)))
864
 
 
865
 
    def test_nested_vars_single_assignment(self):
866
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
867
 
          <py:with vars="x, (y, z) = (1, (2, 3))">${x} ${y} ${z}</py:with>
868
 
        </div>""")
869
 
        self.assertEqual("""<div>
870
 
          1 2 3
871
 
        </div>""", str(tmpl.generate(x=42)))
872
 
 
873
 
    def test_multiple_vars_trailing_semicolon(self):
874
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
875
 
          <py:with vars="x = x * 2; y = x / 2;">${x} ${y}</py:with>
876
 
        </div>""")
877
 
        self.assertEqual("""<div>
878
 
          84 42
879
 
        </div>""", str(tmpl.generate(x=42)))
880
 
 
881
 
    def test_semicolon_escape(self):
882
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
883
 
          <py:with vars="x = 'here is a semicolon: ;'; y = 'here are two semicolons: ;;' ;">
884
 
            ${x}
885
 
            ${y}
886
 
          </py:with>
887
 
        </div>""")
888
 
        self.assertEqual("""<div>
889
 
            here is a semicolon: ;
890
 
            here are two semicolons: ;;
891
 
        </div>""", str(tmpl.generate()))
892
 
 
893
 
    def test_unicode_expr(self):
894
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
895
 
          <span py:with="weeks=(u'一', u'二', u'三', u'四', u'五', u'六', u'日')">
896
 
            $weeks
897
 
          </span>
898
 
        </div>""")
899
 
        self.assertEqual("""<div>
900
 
          <span>
901
 
            一二三四五六日
902
 
          </span>
903
 
        </div>""", str(tmpl.generate()))
904
 
 
905
 
 
906
 
class TemplateTestCase(unittest.TestCase):
907
 
    """Tests for basic template processing, expression evaluation and error
908
 
    reporting.
909
 
    """
910
 
 
911
 
    def test_interpolate_string(self):
912
 
        parts = list(Template._interpolate('bla'))
913
 
        self.assertEqual(1, len(parts))
914
 
        self.assertEqual(Stream.TEXT, parts[0][0])
915
 
        self.assertEqual('bla', parts[0][1])
916
 
 
917
 
    def test_interpolate_simple(self):
918
 
        parts = list(Template._interpolate('${bla}'))
919
 
        self.assertEqual(1, len(parts))
920
 
        self.assertEqual(Template.EXPR, parts[0][0])
921
 
        self.assertEqual('bla', parts[0][1].source)
922
 
 
923
 
    def test_interpolate_escaped(self):
924
 
        parts = list(Template._interpolate('$${bla}'))
925
 
        self.assertEqual(1, len(parts))
926
 
        self.assertEqual(Stream.TEXT, parts[0][0])
927
 
        self.assertEqual('${bla}', parts[0][1])
928
 
 
929
 
    def test_interpolate_short(self):
930
 
        parts = list(Template._interpolate('$bla'))
931
 
        self.assertEqual(1, len(parts))
932
 
        self.assertEqual(Template.EXPR, parts[0][0])
933
 
        self.assertEqual('bla', parts[0][1].source)
934
 
 
935
 
    def test_interpolate_short_starting_with_underscore(self):
936
 
        parts = list(Template._interpolate('$_bla'))
937
 
        self.assertEqual(1, len(parts))
938
 
        self.assertEqual(Template.EXPR, parts[0][0])
939
 
        self.assertEqual('_bla', parts[0][1].source)
940
 
 
941
 
    def test_interpolate_short_containing_underscore(self):
942
 
        parts = list(Template._interpolate('$foo_bar'))
943
 
        self.assertEqual(1, len(parts))
944
 
        self.assertEqual(Template.EXPR, parts[0][0])
945
 
        self.assertEqual('foo_bar', parts[0][1].source)
946
 
 
947
 
    def test_interpolate_short_starting_with_dot(self):
948
 
        parts = list(Template._interpolate('$.bla'))
949
 
        self.assertEqual(1, len(parts))
950
 
        self.assertEqual(Stream.TEXT, parts[0][0])
951
 
        self.assertEqual('$.bla', parts[0][1])
952
 
 
953
 
    def test_interpolate_short_containing_dot(self):
954
 
        parts = list(Template._interpolate('$foo.bar'))
955
 
        self.assertEqual(1, len(parts))
956
 
        self.assertEqual(Template.EXPR, parts[0][0])
957
 
        self.assertEqual('foo.bar', parts[0][1].source)
958
 
 
959
 
    def test_interpolate_short_starting_with_digit(self):
960
 
        parts = list(Template._interpolate('$0bla'))
961
 
        self.assertEqual(1, len(parts))
962
 
        self.assertEqual(Stream.TEXT, parts[0][0])
963
 
        self.assertEqual('$0bla', parts[0][1])
964
 
 
965
 
    def test_interpolate_short_containing_digit(self):
966
 
        parts = list(Template._interpolate('$foo0'))
967
 
        self.assertEqual(1, len(parts))
968
 
        self.assertEqual(Template.EXPR, parts[0][0])
969
 
        self.assertEqual('foo0', parts[0][1].source)
970
 
 
971
 
    def test_interpolate_mixed1(self):
972
 
        parts = list(Template._interpolate('$foo bar $baz'))
973
 
        self.assertEqual(3, len(parts))
974
 
        self.assertEqual(Template.EXPR, parts[0][0])
975
 
        self.assertEqual('foo', parts[0][1].source)
976
 
        self.assertEqual(Stream.TEXT, parts[1][0])
977
 
        self.assertEqual(' bar ', parts[1][1])
978
 
        self.assertEqual(Template.EXPR, parts[2][0])
979
 
        self.assertEqual('baz', parts[2][1].source)
980
 
 
981
 
    def test_interpolate_mixed2(self):
982
 
        parts = list(Template._interpolate('foo $bar baz'))
983
 
        self.assertEqual(3, len(parts))
984
 
        self.assertEqual(Stream.TEXT, parts[0][0])
985
 
        self.assertEqual('foo ', parts[0][1])
986
 
        self.assertEqual(Template.EXPR, parts[1][0])
987
 
        self.assertEqual('bar', parts[1][1].source)
988
 
        self.assertEqual(Stream.TEXT, parts[2][0])
989
 
        self.assertEqual(' baz', parts[2][1])
990
 
 
991
 
 
992
 
class MarkupTemplateTestCase(unittest.TestCase):
993
 
    """Tests for markup template processing."""
994
 
 
995
 
    def test_interpolate_mixed3(self):
996
 
        tmpl = MarkupTemplate('<root> ${var} $var</root>')
997
 
        self.assertEqual('<root> 42 42</root>', str(tmpl.generate(var=42)))
998
 
 
999
 
    def test_interpolate_leading_trailing_space(self):
1000
 
        tmpl = MarkupTemplate('<root>${    foo    }</root>')
1001
 
        self.assertEqual('<root>bar</root>', str(tmpl.generate(foo='bar')))
1002
 
 
1003
 
    def test_interpolate_multiline(self):
1004
 
        tmpl = MarkupTemplate("""<root>${dict(
1005
 
          bar = 'baz'
1006
 
        )[foo]}</root>""")
1007
 
        self.assertEqual('<root>baz</root>', str(tmpl.generate(foo='bar')))
1008
 
 
1009
 
    def test_interpolate_non_string_attrs(self):
1010
 
        tmpl = MarkupTemplate('<root attr="${1}"/>')
1011
 
        self.assertEqual('<root attr="1"/>', str(tmpl.generate()))
1012
 
 
1013
 
    def test_interpolate_list_result(self):
1014
 
        tmpl = MarkupTemplate('<root>$foo</root>')
1015
 
        self.assertEqual('<root>buzz</root>', str(tmpl.generate(foo=('buzz',))))
1016
 
 
1017
 
    def test_empty_attr(self):
1018
 
        tmpl = MarkupTemplate('<root attr=""/>')
1019
 
        self.assertEqual('<root attr=""/>', str(tmpl.generate()))
1020
 
 
1021
 
    def test_bad_directive_error(self):
1022
 
        xml = '<p xmlns:py="http://genshi.edgewall.org/" py:do="nothing" />'
1023
 
        try:
1024
 
            tmpl = MarkupTemplate(xml, filename='test.html')
1025
 
        except BadDirectiveError, e:
1026
 
            self.assertEqual('test.html', e.filename)
1027
 
            if sys.version_info[:2] >= (2, 4):
1028
 
                self.assertEqual(1, e.lineno)
1029
 
 
1030
 
    def test_directive_value_syntax_error(self):
1031
 
        xml = """<p xmlns:py="http://genshi.edgewall.org/" py:if="bar'" />"""
1032
 
        try:
1033
 
            tmpl = MarkupTemplate(xml, filename='test.html')
1034
 
            self.fail('Expected SyntaxError')
1035
 
        except TemplateSyntaxError, e:
1036
 
            self.assertEqual('test.html', e.filename)
1037
 
            if sys.version_info[:2] >= (2, 4):
1038
 
                self.assertEqual(1, e.lineno)
1039
 
 
1040
 
    def test_expression_syntax_error(self):
1041
 
        xml = """<p>
1042
 
          Foo <em>${bar"}</em>
1043
 
        </p>"""
1044
 
        try:
1045
 
            tmpl = MarkupTemplate(xml, filename='test.html')
1046
 
            self.fail('Expected SyntaxError')
1047
 
        except TemplateSyntaxError, e:
1048
 
            self.assertEqual('test.html', e.filename)
1049
 
            if sys.version_info[:2] >= (2, 4):
1050
 
                self.assertEqual(2, e.lineno)
1051
 
 
1052
 
    def test_expression_syntax_error_multi_line(self):
1053
 
        xml = """<p><em></em>
1054
 
 
1055
 
 ${bar"}
1056
 
 
1057
 
        </p>"""
1058
 
        try:
1059
 
            tmpl = MarkupTemplate(xml, filename='test.html')
1060
 
            self.fail('Expected SyntaxError')
1061
 
        except TemplateSyntaxError, e:
1062
 
            self.assertEqual('test.html', e.filename)
1063
 
            if sys.version_info[:2] >= (2, 4):
1064
 
                self.assertEqual(3, e.lineno)
1065
 
 
1066
 
    def test_markup_noescape(self):
1067
 
        """
1068
 
        Verify that outputting context data that is a `Markup` instance is not
1069
 
        escaped.
1070
 
        """
1071
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1072
 
          $myvar
1073
 
        </div>""")
1074
 
        self.assertEqual("""<div>
1075
 
          <b>foo</b>
1076
 
        </div>""", str(tmpl.generate(myvar=Markup('<b>foo</b>'))))
1077
 
 
1078
 
    def test_text_noescape_quotes(self):
1079
 
        """
1080
 
        Verify that outputting context data in text nodes doesn't escape quotes.
1081
 
        """
1082
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1083
 
          $myvar
1084
 
        </div>""")
1085
 
        self.assertEqual("""<div>
1086
 
          "foo"
1087
 
        </div>""", str(tmpl.generate(myvar='"foo"')))
1088
 
 
1089
 
    def test_attr_escape_quotes(self):
1090
 
        """
1091
 
        Verify that outputting context data in attribtes escapes quotes.
1092
 
        """
1093
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1094
 
          <elem class="$myvar"/>
1095
 
        </div>""")
1096
 
        self.assertEqual("""<div>
1097
 
          <elem class="&#34;foo&#34;"/>
1098
 
        </div>""", str(tmpl.generate(myvar='"foo"')))
1099
 
 
1100
 
    def test_directive_element(self):
1101
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1102
 
          <py:if test="myvar">bar</py:if>
1103
 
        </div>""")
1104
 
        self.assertEqual("""<div>
1105
 
          bar
1106
 
        </div>""", str(tmpl.generate(myvar='"foo"')))
1107
 
 
1108
 
    def test_normal_comment(self):
1109
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1110
 
          <!-- foo bar -->
1111
 
        </div>""")
1112
 
        self.assertEqual("""<div>
1113
 
          <!-- foo bar -->
1114
 
        </div>""", str(tmpl.generate()))
1115
 
 
1116
 
    def test_template_comment(self):
1117
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1118
 
          <!-- !foo -->
1119
 
          <!--!bar-->
1120
 
        </div>""")
1121
 
        self.assertEqual("""<div>
1122
 
        </div>""", str(tmpl.generate()))
1123
 
 
1124
 
    def test_parse_with_same_namespace_nested(self):
1125
 
        tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
1126
 
          <span xmlns:py="http://genshi.edgewall.org/">
1127
 
          </span>
1128
 
        </div>""")
1129
 
        self.assertEqual("""<div>
1130
 
          <span>
1131
 
          </span>
1132
 
        </div>""", str(tmpl.generate()))
1133
 
 
1134
 
    def test_latin1_encoded_with_xmldecl(self):
1135
 
        tmpl = MarkupTemplate(u"""<?xml version="1.0" encoding="iso-8859-1" ?>
1136
 
        <div xmlns:py="http://genshi.edgewall.org/">
1137
 
          \xf6
1138
 
        </div>""".encode('iso-8859-1'), encoding='iso-8859-1')
1139
 
        self.assertEqual(u"""<div>
1140
 
          \xf6
1141
 
        </div>""", unicode(tmpl.generate()))
1142
 
 
1143
 
    def test_latin1_encoded_explicit_encoding(self):
1144
 
        tmpl = MarkupTemplate(u"""<div xmlns:py="http://genshi.edgewall.org/">
1145
 
          \xf6
1146
 
        </div>""".encode('iso-8859-1'), encoding='iso-8859-1')
1147
 
        self.assertEqual(u"""<div>
1148
 
          \xf6
1149
 
        </div>""", unicode(tmpl.generate()))
1150
 
 
1151
 
 
1152
 
class TextTemplateTestCase(unittest.TestCase):
1153
 
    """Tests for text template processing."""
1154
 
 
1155
 
    def test_escaping(self):
1156
 
        tmpl = TextTemplate('\\#escaped')
1157
 
        self.assertEqual('#escaped', str(tmpl.generate()))
1158
 
 
1159
 
    def test_comment(self):
1160
 
        tmpl = TextTemplate('## a comment')
1161
 
        self.assertEqual('', str(tmpl.generate()))
1162
 
 
1163
 
    def test_comment_escaping(self):
1164
 
        tmpl = TextTemplate('\\## escaped comment')
1165
 
        self.assertEqual('## escaped comment', str(tmpl.generate()))
1166
 
 
1167
 
    def test_end_with_args(self):
1168
 
        tmpl = TextTemplate("""
1169
 
        #if foo
1170
 
          bar
1171
 
        #end 'if foo'""")
1172
 
        self.assertEqual('\n', str(tmpl.generate()))
1173
 
 
1174
 
    def test_latin1_encoded(self):
1175
 
        text = u'$foo\xf6$bar'.encode('iso-8859-1')
1176
 
        tmpl = TextTemplate(text, encoding='iso-8859-1')
1177
 
        self.assertEqual(u'x\xf6y', unicode(tmpl.generate(foo='x', bar='y')))
1178
 
 
1179
 
    def test_empty_lines1(self):
1180
 
        tmpl = TextTemplate("""Your items:
1181
 
 
1182
 
        #for item in items
1183
 
          * ${item}
1184
 
        #end""")
1185
 
        self.assertEqual("""Your items:
1186
 
 
1187
 
          * 0
1188
 
          * 1
1189
 
          * 2
1190
 
""", tmpl.generate(items=range(3)).render('text'))
1191
 
 
1192
 
    def test_empty_lines2(self):
1193
 
        tmpl = TextTemplate("""Your items:
1194
 
 
1195
 
        #for item in items
1196
 
          * ${item}
1197
 
 
1198
 
        #end""")
1199
 
        self.assertEqual("""Your items:
1200
 
 
1201
 
          * 0
1202
 
 
1203
 
          * 1
1204
 
 
1205
 
          * 2
1206
 
 
1207
 
""", tmpl.generate(items=range(3)).render('text'))
1208
 
 
1209
 
 
1210
 
class TemplateLoaderTestCase(unittest.TestCase):
1211
 
    """Tests for the template loader."""
1212
 
 
1213
 
    def setUp(self):
1214
 
        self.dirname = tempfile.mkdtemp(suffix='markup_test')
1215
 
 
1216
 
    def tearDown(self):
1217
 
        shutil.rmtree(self.dirname)
1218
 
 
1219
 
    def test_relative_include_samedir(self):
1220
 
        file1 = open(os.path.join(self.dirname, 'tmpl1.html'), 'w')
1221
 
        try:
1222
 
            file1.write("""<div>Included</div>""")
1223
 
        finally:
1224
 
            file1.close()
1225
 
 
1226
 
        file2 = open(os.path.join(self.dirname, 'tmpl2.html'), 'w')
1227
 
        try:
1228
 
            file2.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude">
1229
 
              <xi:include href="tmpl1.html" />
1230
 
            </html>""")
1231
 
        finally:
1232
 
            file2.close()
1233
 
 
1234
 
        loader = TemplateLoader([self.dirname])
1235
 
        tmpl = loader.load('tmpl2.html')
1236
 
        self.assertEqual("""<html>
1237
 
              <div>Included</div>
1238
 
            </html>""", tmpl.generate().render())
1239
 
 
1240
 
    def test_relative_include_subdir(self):
1241
 
        os.mkdir(os.path.join(self.dirname, 'sub'))
1242
 
        file1 = open(os.path.join(self.dirname, 'sub', 'tmpl1.html'), 'w')
1243
 
        try:
1244
 
            file1.write("""<div>Included</div>""")
1245
 
        finally:
1246
 
            file1.close()
1247
 
 
1248
 
        file2 = open(os.path.join(self.dirname, 'tmpl2.html'), 'w')
1249
 
        try:
1250
 
            file2.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude">
1251
 
              <xi:include href="sub/tmpl1.html" />
1252
 
            </html>""")
1253
 
        finally:
1254
 
            file2.close()
1255
 
 
1256
 
        loader = TemplateLoader([self.dirname])
1257
 
        tmpl = loader.load('tmpl2.html')
1258
 
        self.assertEqual("""<html>
1259
 
              <div>Included</div>
1260
 
            </html>""", tmpl.generate().render())
1261
 
 
1262
 
    def test_relative_include_parentdir(self):
1263
 
        file1 = open(os.path.join(self.dirname, 'tmpl1.html'), 'w')
1264
 
        try:
1265
 
            file1.write("""<div>Included</div>""")
1266
 
        finally:
1267
 
            file1.close()
1268
 
 
1269
 
        os.mkdir(os.path.join(self.dirname, 'sub'))
1270
 
        file2 = open(os.path.join(self.dirname, 'sub', 'tmpl2.html'), 'w')
1271
 
        try:
1272
 
            file2.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude">
1273
 
              <xi:include href="../tmpl1.html" />
1274
 
            </html>""")
1275
 
        finally:
1276
 
            file2.close()
1277
 
 
1278
 
        loader = TemplateLoader([self.dirname])
1279
 
        tmpl = loader.load('sub/tmpl2.html')
1280
 
        self.assertEqual("""<html>
1281
 
              <div>Included</div>
1282
 
            </html>""", tmpl.generate().render())
1283
 
 
1284
 
    def test_relative_include_without_search_path(self):
1285
 
        file1 = open(os.path.join(self.dirname, 'tmpl1.html'), 'w')
1286
 
        try:
1287
 
            file1.write("""<div>Included</div>""")
1288
 
        finally:
1289
 
            file1.close()
1290
 
 
1291
 
        file2 = open(os.path.join(self.dirname, 'tmpl2.html'), 'w')
1292
 
        try:
1293
 
            file2.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude">
1294
 
              <xi:include href="tmpl1.html" />
1295
 
            </html>""")
1296
 
        finally:
1297
 
            file2.close()
1298
 
 
1299
 
        loader = TemplateLoader()
1300
 
        tmpl = loader.load(os.path.join(self.dirname, 'tmpl2.html'))
1301
 
        self.assertEqual("""<html>
1302
 
              <div>Included</div>
1303
 
            </html>""", tmpl.generate().render())
1304
 
 
1305
 
    def test_relative_include_without_search_path_nested(self):
1306
 
        file1 = open(os.path.join(self.dirname, 'tmpl1.html'), 'w')
1307
 
        try:
1308
 
            file1.write("""<div>Included</div>""")
1309
 
        finally:
1310
 
            file1.close()
1311
 
 
1312
 
        file2 = open(os.path.join(self.dirname, 'tmpl2.html'), 'w')
1313
 
        try:
1314
 
            file2.write("""<div xmlns:xi="http://www.w3.org/2001/XInclude">
1315
 
              <xi:include href="tmpl1.html" />
1316
 
            </div>""")
1317
 
        finally:
1318
 
            file2.close()
1319
 
 
1320
 
        file3 = open(os.path.join(self.dirname, 'tmpl3.html'), 'w')
1321
 
        try:
1322
 
            file3.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude">
1323
 
              <xi:include href="tmpl2.html" />
1324
 
            </html>""")
1325
 
        finally:
1326
 
            file3.close()
1327
 
 
1328
 
        loader = TemplateLoader()
1329
 
        tmpl = loader.load(os.path.join(self.dirname, 'tmpl3.html'))
1330
 
        self.assertEqual("""<html>
1331
 
              <div>
1332
 
              <div>Included</div>
1333
 
            </div>
1334
 
            </html>""", tmpl.generate().render())
1335
 
 
1336
 
    def test_relative_include_from_inmemory_template(self):
1337
 
        file1 = open(os.path.join(self.dirname, 'tmpl1.html'), 'w')
1338
 
        try:
1339
 
            file1.write("""<div>Included</div>""")
1340
 
        finally:
1341
 
            file1.close()
1342
 
 
1343
 
        loader = TemplateLoader([self.dirname])
1344
 
        tmpl2 = MarkupTemplate("""<html xmlns:xi="http://www.w3.org/2001/XInclude">
1345
 
          <xi:include href="../tmpl1.html" />
1346
 
        </html>""", filename='subdir/tmpl2.html', loader=loader)
1347
 
 
1348
 
        self.assertEqual("""<html>
1349
 
          <div>Included</div>
1350
 
        </html>""", tmpl2.generate().render())
1351
 
 
1352
 
    def test_load_with_default_encoding(self):
1353
 
        f = open(os.path.join(self.dirname, 'tmpl.html'), 'w')
1354
 
        try:
1355
 
            f.write(u'<div>\xf6</div>'.encode('iso-8859-1'))
1356
 
        finally:
1357
 
            f.close()
1358
 
        loader = TemplateLoader([self.dirname], default_encoding='iso-8859-1')
1359
 
        loader.load('tmpl.html')
1360
 
 
1361
 
    def test_load_with_explicit_encoding(self):
1362
 
        f = open(os.path.join(self.dirname, 'tmpl.html'), 'w')
1363
 
        try:
1364
 
            f.write(u'<div>\xf6</div>'.encode('iso-8859-1'))
1365
 
        finally:
1366
 
            f.close()
1367
 
        loader = TemplateLoader([self.dirname], default_encoding='utf-8')
1368
 
        loader.load('tmpl.html', encoding='iso-8859-1')
1369
 
 
1370
 
 
1371
 
def suite():
1372
 
    suite = unittest.TestSuite()
1373
 
    suite.addTest(doctest.DocTestSuite(template))
1374
 
    suite.addTest(unittest.makeSuite(AttrsDirectiveTestCase, 'test'))
1375
 
    suite.addTest(unittest.makeSuite(ChooseDirectiveTestCase, 'test'))
1376
 
    suite.addTest(unittest.makeSuite(DefDirectiveTestCase, 'test'))
1377
 
    suite.addTest(unittest.makeSuite(ForDirectiveTestCase, 'test'))
1378
 
    suite.addTest(unittest.makeSuite(IfDirectiveTestCase, 'test'))
1379
 
    suite.addTest(unittest.makeSuite(MatchDirectiveTestCase, 'test'))
1380
 
    suite.addTest(unittest.makeSuite(StripDirectiveTestCase, 'test'))
1381
 
    suite.addTest(unittest.makeSuite(WithDirectiveTestCase, 'test'))
1382
 
    suite.addTest(unittest.makeSuite(TemplateTestCase, 'test'))
1383
 
    suite.addTest(unittest.makeSuite(MarkupTemplateTestCase, 'test'))
1384
 
    suite.addTest(unittest.makeSuite(TextTemplateTestCase, 'test'))
1385
 
    suite.addTest(unittest.makeSuite(TemplateLoaderTestCase, 'test'))
1386
 
    return suite
1387
 
 
1388
 
if __name__ == '__main__':
1389
 
    unittest.main(defaultTest='suite')