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