root / trunk / breve / tests / templates.py

Revision 403, 16.4 kB (checked in by cliff, 7 months ago)

more tests

Line 
1# -*- coding: utf-8 -*-
2
3import os, sys
4import doctest, unittest
5from datetime import datetime
6
7if __name__ == '__main__':
8    # force import from source directory rather than site-packages
9    sys.path.insert ( 0, os.path.abspath ( '../..' ) )
10    import breve
11
12from breve.tags.html import tags as html
13from breve.flatten import flatten 
14from breve import Template, register_flattener, register_global, escape
15from breve.globals import push, pop, get_stacks
16from breve.tests.lib import diff, template_root, my_name, expected_output
17
18class TemplateTestCase ( unittest.TestCase ):
19    def test_instantiation_parameters ( self ):
20        '''test instantiation parameters'''
21        # change the defaults to something else
22        args = { 
23            'tidy': True, 
24            'debug': True, 
25            'namespace': 'v', 
26            'mashup_entities': True, 
27            'extension': '.breve'
28        }
29        t = Template ( html, root = template_root ( ), **args )
30        for k, v in args.items ( ):
31            self.failUnless ( getattr ( t, k ) == v )
32
33    def test_render_parameters ( self ):
34        '''test render-time parameters'''
35       
36        vars = dict ( 
37            message = 'hello, from breve',
38            title = my_name ( )
39        )
40        args = { 
41            'tidy': True, 
42            'debug': True, 
43            'namespace': 'v', 
44            'extension': '.breve'
45        }
46        t = Template ( html, root = template_root ( ) )
47        t.render ( 'index', vars, **args )
48        for k, v in args.items ( ):
49            self.failUnless ( getattr ( t, k ) == v )
50   
51    def test_simple_template ( self ):
52        '''simple template'''
53
54        vars = dict ( 
55            message = 'hello, from breve',
56            title = my_name ( )
57        )
58        t = Template ( html, root = template_root ( ) )
59        actual = t.render ( 'index', vars, namespace = 'v' )
60        expected = expected_output ( )
61        try:
62            self.assertEqual ( actual, expected )
63        except AssertionError:
64            diff ( actual, expected )
65            raise
66
67    def test_include ( self ):
68        '''include() directive'''
69
70        vars = dict ( 
71            message = 'hello, from breve',
72            title = my_name ( )
73        )
74        t = Template ( html, root = template_root ( ) )
75        actual = t.render ( 'index', vars, namespace = 'v' )
76        expected = expected_output ( )
77        try:
78            self.assertEqual ( actual, expected )
79        except AssertionError:
80            diff ( actual, expected )
81            raise
82
83    def test_nested_include ( self ):
84        '''nested include() directives'''
85
86        vars = dict ( 
87            message = 'hello, from breve',
88            title = my_name ( )
89        )
90        t = Template ( html, root = template_root ( ) )
91        actual = t.render ( 'index', vars, namespace = 'v' )
92        expected = expected_output ( )
93        try:
94            self.assertEqual ( actual, expected )
95        except AssertionError:
96            diff ( actual, expected )
97            raise
98
99    def test_loop_include ( self ):
100        '''looping over include() with listcomp'''
101
102        vars = dict ( 
103            message = 'hello, from breve',
104            title = my_name ( )
105        )
106        t = Template ( html, root = template_root ( ) )
107        actual = t.render ( 'index', vars, namespace = 'v' )
108        expected = expected_output ( )
109        try:
110            self.assertEqual ( actual, expected )
111        except AssertionError:
112            diff ( actual, expected )
113            raise
114
115    def test_let_directive ( self ):
116        '''test let directive'''
117       
118        vars = dict ( 
119            message = 'hello, from breve',
120            title = my_name ( )
121        )
122        t = Template ( html, root = template_root ( ) )
123        actual = t.render ( 'index', vars, namespace = 'v' )
124        expected = expected_output ( )
125        try:
126            self.assertEqual ( actual, expected )
127        except AssertionError:
128            diff ( actual, expected )
129            raise
130       
131    def test_let_directive_scope ( self ):
132        '''test let directive's scope'''
133       
134        vars = dict ( 
135            message = 'hello, from breve',
136            title = my_name ( ),
137            do_fail = False
138        )
139
140        # don't fail - use variable in scope
141        t = Template ( html, root = template_root ( ) )
142        actual = t.render ( 'index', vars, namespace = 'v' )
143        expected = expected_output ( )
144        try:
145            self.assertEqual ( actual, expected )
146        except AssertionError:
147            diff ( actual, expected )
148            raise
149
150        # do fail - try to use the variable out of scope
151        vars [ 'do_fail' ] = True
152        t = Template ( html, root = template_root ( ) )
153        self.failUnlessRaises (
154            NameError,
155            t.render, 'index', vars, namespace = 'v'
156        )
157
158    def test_assign_scope ( self ):
159        '''test assign directive's scope'''
160
161        vars = dict (
162            message = 'hello, from breve',
163            title = my_name ( )
164        )
165
166        # don't fail - use variable in scope                                                                                             
167        t = Template ( html, root = template_root ( ) )
168        actual = t.render ( 'index', vars, namespace = 'v' )
169        expected = expected_output ( )
170        try:
171            self.assertEqual ( actual, expected )
172        except AssertionError:
173            diff ( actual, expected )
174            raise
175       
176    def test_include_macros ( self ):
177        '''define macros via include() directive'''
178
179        vars = dict ( 
180            message = 'hello, from breve',
181            title = my_name ( )
182        )
183        t = Template ( html, root = template_root ( ) )
184        actual = t.render ( 'index', vars, namespace = 'v' )
185        expected = expected_output ( )
186        try:
187            self.assertEqual ( actual, expected )
188        except AssertionError:
189            diff ( actual, expected )
190            raise
191
192    def test_nested_include_macros ( self ):
193        '''define macros inside nested include() directives'''
194
195        vars = dict ( 
196            message = 'hello, from breve',
197            title = my_name ( )
198        )
199        t = Template ( html, root = template_root ( ) )
200        actual = t.render ( 'index', vars, namespace = 'v' )
201        expected = expected_output ( )
202        try:
203            self.assertEqual ( actual, expected )
204        except AssertionError:
205            diff ( actual, expected )
206            raise
207
208    def test_loop_macros ( self ):
209        '''loop using macro'''
210
211        vars = dict ( 
212            message = 'hello, from breve',
213            title = my_name ( ),
214            url_data = [
215                dict ( url = 'http://www.google.com', label = 'Google' ),
216                dict ( url = 'http://www.yahoo.com', label = 'Yahoo!' ),
217                dict ( url = 'http://www.amazon.com', label = 'Amazon' )
218            ]
219        )
220        t = Template ( html, root = template_root ( ) )
221        actual = t.render ( 'index', vars, namespace = 'v' )
222        expected = expected_output ( )
223        try:
224            self.assertEqual ( actual, expected )
225        except AssertionError:
226            diff ( actual, expected )
227            raise
228
229    def test_macro_includes ( self ):
230        '''include() directive inside macro'''
231
232        vars = dict ( 
233            message = 'hello, from breve',
234            title = my_name ( )
235        )
236        t = Template ( html, root = template_root ( ) )
237        actual = t.render ( 'index', vars, namespace = 'v' )
238        expected = expected_output ( )
239        try:
240            self.assertEqual ( actual, expected )
241        except AssertionError:
242            diff ( actual, expected )
243            raise
244
245    def test_simple_inheritance ( self ):
246        '''simple inheritance'''
247
248        vars = dict ( 
249            message = 'hello, from breve',
250            title = my_name ( )
251        )
252        test_name = my_name ( )
253        t = Template ( html, root = template_root ( ) )
254        actual = t.render ( 'index', vars, namespace = 'v' )
255        expected = expected_output ( )
256        try:
257            self.assertEqual ( actual, expected )
258        except AssertionError:
259            diff ( actual, expected )
260            raise
261
262    def test_nested_inheritance ( self ):
263        '''nested inheritance'''
264
265        vars = dict ( 
266            message = 'hello, from breve',
267            title = my_name ( )
268        )
269        t = Template ( html, root = template_root ( ) )
270        actual = t.render ( 'index', vars, namespace = 'v' )
271        expected = expected_output ( )
272        try:
273            self.assertEqual ( actual, expected )
274        except AssertionError:
275            diff ( actual, expected )
276            raise
277
278    def test_macros_inside_inherits ( self ):
279        '''test macros inside inherits(): scope issues'''
280
281        # note: I'm not convinced this is the desired behaviour, but
282        # it's *compatible* behaviour.
283       
284        vars = dict (
285            title = my_name ( ),
286            message = 'Hello, from breve'
287        )
288        t = Template ( html, root = template_root ( ) )
289        actual = t.render ( 'index', vars, namespace = 'v' )
290        expected = expected_output ( )
291        try:
292            self.assertEqual ( actual, expected )
293        except AssertionError:
294            diff ( actual, expected )
295            raise
296
297
298    def test_register_global ( self ):
299        '''register_global() function'''
300
301        vars = dict ( 
302            title = my_name ( )
303        )
304        register_global ( 'global_message', 'This is a global variable' )
305
306        test_name = my_name ( )
307        t = Template ( html, root = template_root ( ) )
308        actual = t.render ( 'index', vars, namespace = 'v' )
309        expected = expected_output ( )
310        try:
311            self.assertEqual ( actual, expected )
312        except AssertionError:
313            diff ( actual, expected )
314            raise
315
316    def test_stacks ( self ):
317        '''test stacks (push/pop)'''
318       
319        push ( a = 1, b = 2 )
320        self.failUnless ( 
321            pop ( 'a' ) == 1 and pop ( 'b' ) == 2
322        )
323
324    def test_stacks_template ( self ):
325        '''test stacks in template'''
326       
327        vars = dict ( 
328            title = my_name ( ),
329            message = 'hello, from breve'
330        )
331        t = Template ( html, root = template_root ( ) )
332        actual = t.render ( 'index', vars, namespace = 'v' )
333        expected = expected_output ( )
334
335        try:
336            self.assertEqual ( actual, expected )
337        except AssertionError:
338            diff ( actual, expected )
339            raise
340
341        # stack should be empty when we finish
342        self.failUnless ( not get_stacks ( ) )
343       
344    def test_register_flattener ( self ):
345        '''register_flattener() function'''
346
347        def flatten_date ( o ):
348            return escape ( o.strftime ( '%Y/%m/%d' ) )
349        register_flattener ( datetime, flatten_date )
350        register_global ( 'flatten_date', flatten_date )
351
352        vars = dict ( 
353            title = my_name ( ),
354            today = datetime ( 2008, 4, 17 )
355        )
356        test_name = my_name ( )
357        t = Template ( html, root = template_root ( ) )
358        actual = t.render ( 'index', vars, namespace = 'v' )
359        expected = expected_output ( )
360        try:
361            self.assertEqual ( actual, expected )
362        except AssertionError:
363            diff ( actual, expected )
364            raise
365
366    def test_custom_renderer ( self ):
367        '''custom renderer'''
368
369        def render_row ( tag, data ):
370            T = html
371            tag.clear ( )
372            return tag [
373                [ T.td [ _i ] for _i in data ]
374            ]
375        register_global ( 'render_row', render_row )
376
377        vars = dict ( 
378            title = my_name ( ),
379            my_data = [
380                range ( 5 ),
381                range ( 5, 10 ),
382                range ( 10, 15 )
383            ]
384        )
385        t = Template ( html, root = template_root ( ) )
386        actual = t.render ( 'index', vars, namespace = 'v' )
387        expected = expected_output ( )
388        try:
389            self.assertEqual ( actual, expected )
390        except AssertionError:
391            diff ( actual, expected )
392            raise
393   
394    def test_custom_renderer_notag ( self ):
395        '''custom renderer returning non-Tag type'''
396
397        def render_text ( tag, data ):
398            tag.clear ( )
399            return data
400        register_global ( 'render_text', render_text )
401
402        vars = dict ( 
403            title = my_name ( ),
404            message = 'hello, world'
405        )
406        t = Template ( html, root = template_root ( ) )
407        actual = t.render ( 'index', vars, namespace = 'v' )
408        expected = expected_output ( )
409        try:
410            self.assertEqual ( actual, expected )
411        except AssertionError:
412            diff ( actual, expected )
413            raise
414
415    def test_custom_loader ( self ):
416        '''custom loader'''
417
418        class PathLoader ( object ):
419            __slots__ = [ 'paths' ]
420
421            def __init__ ( self, *paths ):
422                self.paths = paths
423
424            def stat ( self, template, root ):
425                for p in self.paths:
426                    f = os.path.join ( root, p, template )
427                    if os.path.isfile ( f ):
428                        timestamp = long ( os.stat ( f ).st_mtime )
429                        uid = f
430                        return uid, timestamp
431                raise OSError, 'No such file or directory %s' % template
432
433            def load ( self, uid ):
434                return file ( uid, 'U' ).read ( )
435
436        loader = PathLoader ( 
437            template_root ( ), 
438            os.path.join ( template_root ( ), 'path1' ), 
439            os.path.join ( template_root ( ), 'path2' ), 
440            os.path.join ( template_root ( ), 'path3' ), 
441        )
442       
443        vars = dict ( 
444            title = my_name ( ),
445            message = 'hello, world'
446        )
447        test_name = my_name ( )
448        t = Template ( html ) # note we're not setting root
449        actual = t.render ( 'index', vars, namespace = 'v', loader = loader )
450        expected = expected_output ( )
451        try:
452            self.assertEqual ( actual, expected )
453        except AssertionError:
454            diff ( actual, expected )
455            raise
456
457    def test_custom_loader_stack ( self ):
458        '''custom loader stack'''
459
460        class PathLoader ( object ):
461            __slots__ = [ 'paths' ]
462
463            def __init__ ( self, *paths ):
464                self.paths = paths
465
466            def stat ( self, template, root ):
467                for p in self.paths:
468                    f = os.path.join ( root, p, template )
469                    if os.path.isfile ( f ):
470                        timestamp = long ( os.stat ( f ).st_mtime )
471                        uid = f
472                        return uid, timestamp
473                raise OSError, 'No such file or directory %s' % template
474
475            def load ( self, uid ):
476                return file ( uid, 'U' ).read ( )
477
478        loader = PathLoader ( 
479            template_root ( ), 
480            os.path.join ( template_root ( ), 'path1' ), 
481            os.path.join ( template_root ( ), 'path2' ), 
482            os.path.join ( template_root ( ), 'path3' ), 
483        )
484        register_global ( 'path_loader', loader )
485       
486        vars = dict ( 
487            title = my_name ( ),
488            message = 'hello, world'
489        )
490        test_name = my_name ( )
491        t = Template ( html, root = template_root ( ) ) 
492        actual = t.render ( 'index', vars, namespace = 'v' )
493        expected = expected_output ( )
494        try:
495            self.assertEqual ( actual, expected )
496        except AssertionError:
497            diff ( actual, expected )
498            raise
499
500class TemplateMemoryTestCase ( unittest.TestCase ):
501
502    def test_let_memory_freed ( self ):
503        '''test that let() objects are freed'''
504
505        # is this even meaningful?
506
507        import gc
508        vars = dict (
509            title = my_name ( ),
510            message = "memory test",
511