1import unittest 2 3from mako import compat 4from mako import lookup 5from test.util import result_lines 6 7 8class InheritanceTest(unittest.TestCase): 9 def test_basic(self): 10 collection = lookup.TemplateLookup() 11 12 collection.put_string( 13 "main", 14 """ 15<%inherit file="base"/> 16 17<%def name="header()"> 18 main header. 19</%def> 20 21this is the content. 22""", 23 ) 24 25 collection.put_string( 26 "base", 27 """ 28This is base. 29 30header: ${self.header()} 31 32body: ${self.body()} 33 34footer: ${self.footer()} 35 36<%def name="footer()"> 37 this is the footer. header again ${next.header()} 38</%def> 39""", 40 ) 41 42 assert result_lines(collection.get_template("main").render()) == [ 43 "This is base.", 44 "header:", 45 "main header.", 46 "body:", 47 "this is the content.", 48 "footer:", 49 "this is the footer. header again", 50 "main header.", 51 ] 52 53 def test_multilevel_nesting(self): 54 collection = lookup.TemplateLookup() 55 56 collection.put_string( 57 "main", 58 """ 59<%inherit file="layout"/> 60<%def name="d()">main_d</%def> 61main_body ${parent.d()} 62full stack from the top: 63 ${self.name} ${parent.name} ${parent.context['parent'].name} """ 64 """${parent.context['parent'].context['parent'].name} 65""", 66 ) 67 68 collection.put_string( 69 "layout", 70 """ 71<%inherit file="general"/> 72<%def name="d()">layout_d</%def> 73layout_body 74parent name: ${parent.name} 75${parent.d()} 76${parent.context['parent'].d()} 77${next.body()} 78""", 79 ) 80 81 collection.put_string( 82 "general", 83 """ 84<%inherit file="base"/> 85<%def name="d()">general_d</%def> 86general_body 87${next.d()} 88${next.context['next'].d()} 89${next.body()} 90""", 91 ) 92 collection.put_string( 93 "base", 94 """ 95base_body 96full stack from the base: 97 ${self.name} ${self.context['parent'].name} """ 98 """${self.context['parent'].context['parent'].name} """ 99 """${self.context['parent'].context['parent'].context['parent'].name} 100${next.body()} 101<%def name="d()">base_d</%def> 102""", 103 ) 104 105 assert result_lines(collection.get_template("main").render()) == [ 106 "base_body", 107 "full stack from the base:", 108 "self:main self:layout self:general self:base", 109 "general_body", 110 "layout_d", 111 "main_d", 112 "layout_body", 113 "parent name: self:general", 114 "general_d", 115 "base_d", 116 "main_body layout_d", 117 "full stack from the top:", 118 "self:main self:layout self:general self:base", 119 ] 120 121 def test_includes(self): 122 """test that an included template also has its full hierarchy 123 invoked.""" 124 collection = lookup.TemplateLookup() 125 126 collection.put_string( 127 "base", 128 """ 129 <%def name="a()">base_a</%def> 130 This is the base. 131 ${next.body()} 132 End base. 133""", 134 ) 135 136 collection.put_string( 137 "index", 138 """ 139 <%inherit file="base"/> 140 this is index. 141 a is: ${self.a()} 142 <%include file="secondary"/> 143""", 144 ) 145 146 collection.put_string( 147 "secondary", 148 """ 149 <%inherit file="base"/> 150 this is secondary. 151 a is: ${self.a()} 152""", 153 ) 154 155 assert result_lines(collection.get_template("index").render()) == [ 156 "This is the base.", 157 "this is index.", 158 "a is: base_a", 159 "This is the base.", 160 "this is secondary.", 161 "a is: base_a", 162 "End base.", 163 "End base.", 164 ] 165 166 def test_namespaces(self): 167 """test that templates used via <%namespace> have access to an 168 inheriting 'self', and that the full 'self' is also exported.""" 169 collection = lookup.TemplateLookup() 170 171 collection.put_string( 172 "base", 173 """ 174 <%def name="a()">base_a</%def> 175 <%def name="b()">base_b</%def> 176 This is the base. 177 ${next.body()} 178""", 179 ) 180 181 collection.put_string( 182 "layout", 183 """ 184 <%inherit file="base"/> 185 <%def name="a()">layout_a</%def> 186 This is the layout.. 187 ${next.body()} 188""", 189 ) 190 191 collection.put_string( 192 "index", 193 """ 194 <%inherit file="base"/> 195 <%namespace name="sc" file="secondary"/> 196 this is index. 197 a is: ${self.a()} 198 sc.a is: ${sc.a()} 199 sc.b is: ${sc.b()} 200 sc.c is: ${sc.c()} 201 sc.body is: ${sc.body()} 202""", 203 ) 204 205 collection.put_string( 206 "secondary", 207 """ 208 <%inherit file="layout"/> 209 <%def name="c()">secondary_c. a is ${self.a()} b is ${self.b()} """ 210 """d is ${self.d()}</%def> 211 <%def name="d()">secondary_d.</%def> 212 this is secondary. 213 a is: ${self.a()} 214 c is: ${self.c()} 215""", 216 ) 217 218 assert result_lines(collection.get_template("index").render()) == [ 219 "This is the base.", 220 "this is index.", 221 "a is: base_a", 222 "sc.a is: layout_a", 223 "sc.b is: base_b", 224 "sc.c is: secondary_c. a is layout_a b is base_b d is " 225 "secondary_d.", 226 "sc.body is:", 227 "this is secondary.", 228 "a is: layout_a", 229 "c is: secondary_c. a is layout_a b is base_b d is secondary_d.", 230 ] 231 232 def test_pageargs(self): 233 collection = lookup.TemplateLookup() 234 collection.put_string( 235 "base", 236 """ 237 this is the base. 238 239 <% 240 sorted_ = pageargs.items() 241 sorted_ = sorted(sorted_) 242 %> 243 pageargs: (type: ${type(pageargs)}) ${sorted_} 244 <%def name="foo()"> 245 ${next.body(**context.kwargs)} 246 </%def> 247 248 ${foo()} 249 """, 250 ) 251 collection.put_string( 252 "index", 253 """ 254 <%inherit file="base"/> 255 <%page args="x, y, z=7"/> 256 print ${x}, ${y}, ${z} 257 """, 258 ) 259 260 if compat.py3k: 261 assert result_lines( 262 collection.get_template("index").render_unicode(x=5, y=10) 263 ) == [ 264 "this is the base.", 265 "pageargs: (type: <class 'dict'>) [('x', 5), ('y', 10)]", 266 "print 5, 10, 7", 267 ] 268 else: 269 assert result_lines( 270 collection.get_template("index").render_unicode(x=5, y=10) 271 ) == [ 272 "this is the base.", 273 "pageargs: (type: <type 'dict'>) [('x', 5), ('y', 10)]", 274 "print 5, 10, 7", 275 ] 276 277 def test_pageargs_2(self): 278 collection = lookup.TemplateLookup() 279 collection.put_string( 280 "base", 281 """ 282 this is the base. 283 284 ${next.body(**context.kwargs)} 285 286 <%def name="foo(**kwargs)"> 287 ${next.body(**kwargs)} 288 </%def> 289 290 <%def name="bar(**otherargs)"> 291 ${next.body(z=16, **context.kwargs)} 292 </%def> 293 294 ${foo(x=12, y=15, z=8)} 295 ${bar(x=19, y=17)} 296 """, 297 ) 298 collection.put_string( 299 "index", 300 """ 301 <%inherit file="base"/> 302 <%page args="x, y, z=7"/> 303 pageargs: ${x}, ${y}, ${z} 304 """, 305 ) 306 assert result_lines( 307 collection.get_template("index").render(x=5, y=10) 308 ) == [ 309 "this is the base.", 310 "pageargs: 5, 10, 7", 311 "pageargs: 12, 15, 8", 312 "pageargs: 5, 10, 16", 313 ] 314 315 def test_pageargs_err(self): 316 collection = lookup.TemplateLookup() 317 collection.put_string( 318 "base", 319 """ 320 this is the base. 321 ${next.body()} 322 """, 323 ) 324 collection.put_string( 325 "index", 326 """ 327 <%inherit file="base"/> 328 <%page args="x, y, z=7"/> 329 print ${x}, ${y}, ${z} 330 """, 331 ) 332 try: 333 print(collection.get_template("index").render(x=5, y=10)) 334 assert False 335 except TypeError: 336 assert True 337 338 def test_toplevel(self): 339 collection = lookup.TemplateLookup() 340 collection.put_string( 341 "base", 342 """ 343 this is the base. 344 ${next.body()} 345 """, 346 ) 347 collection.put_string( 348 "index", 349 """ 350 <%inherit file="base"/> 351 this is the body 352 """, 353 ) 354 assert result_lines(collection.get_template("index").render()) == [ 355 "this is the base.", 356 "this is the body", 357 ] 358 assert result_lines( 359 collection.get_template("index").get_def("body").render() 360 ) == ["this is the body"] 361 362 def test_dynamic(self): 363 collection = lookup.TemplateLookup() 364 collection.put_string( 365 "base", 366 """ 367 this is the base. 368 ${next.body()} 369 """, 370 ) 371 collection.put_string( 372 "index", 373 """ 374 <%! 375 def dyn(context): 376 if context.get('base', None) is not None: 377 return 'base' 378 else: 379 return None 380 %> 381 <%inherit file="${dyn(context)}"/> 382 this is index. 383 """, 384 ) 385 assert result_lines(collection.get_template("index").render()) == [ 386 "this is index." 387 ] 388 assert result_lines( 389 collection.get_template("index").render(base=True) 390 ) == ["this is the base.", "this is index."] 391 392 def test_in_call(self): 393 collection = lookup.TemplateLookup() 394 collection.put_string( 395 "/layout.html", 396 """ 397 Super layout! 398 <%call expr="self.grid()"> 399 ${next.body()} 400 </%call> 401 Oh yea! 402 403 <%def name="grid()"> 404 Parent grid 405 ${caller.body()} 406 End Parent 407 </%def> 408 """, 409 ) 410 411 collection.put_string( 412 "/subdir/layout.html", 413 """ 414 ${next.body()} 415 <%def name="grid()"> 416 Subdir grid 417 ${caller.body()} 418 End subdir 419 </%def> 420 <%inherit file="/layout.html"/> 421 """, 422 ) 423 424 collection.put_string( 425 "/subdir/renderedtemplate.html", 426 """ 427 Holy smokes! 428 <%inherit file="/subdir/layout.html"/> 429 """, 430 ) 431 432 assert result_lines( 433 collection.get_template("/subdir/renderedtemplate.html").render() 434 ) == [ 435 "Super layout!", 436 "Subdir grid", 437 "Holy smokes!", 438 "End subdir", 439 "Oh yea!", 440 ] 441