1from mako import exceptions 2from mako.lookup import TemplateLookup 3from mako.template import Template 4from mako.testing.assertions import assert_raises_message 5from mako.testing.fixtures import TemplateTest 6from mako.testing.helpers import result_lines 7 8 9class BlockTest(TemplateTest): 10 def test_anonymous_block_namespace_raises(self): 11 assert_raises_message( 12 exceptions.CompileException, 13 "Can't put anonymous blocks inside <%namespace>", 14 Template, 15 """ 16 <%namespace name="foo"> 17 <%block> 18 block 19 </%block> 20 </%namespace> 21 """, 22 ) 23 24 def test_anonymous_block_in_call(self): 25 template = Template( 26 """ 27 28 <%self:foo x="5"> 29 <%block> 30 this is the block x 31 </%block> 32 </%self:foo> 33 34 <%def name="foo(x)"> 35 foo: 36 ${caller.body()} 37 </%def> 38 """ 39 ) 40 self._do_test( 41 template, ["foo:", "this is the block x"], filters=result_lines 42 ) 43 44 def test_named_block_in_call(self): 45 assert_raises_message( 46 exceptions.CompileException, 47 "Named block 'y' not allowed inside of <%call> tag", 48 Template, 49 """ 50 51 <%self:foo x="5"> 52 <%block name="y"> 53 this is the block 54 </%block> 55 </%self:foo> 56 57 <%def name="foo(x)"> 58 foo: 59 ${caller.body()} 60 ${caller.y()} 61 </%def> 62 """, 63 ) 64 65 def test_name_collision_blocks_toplevel(self): 66 assert_raises_message( 67 exceptions.CompileException, 68 "%def or %block named 'x' already exists in this template", 69 Template, 70 """ 71 <%block name="x"> 72 block 73 </%block> 74 75 foob 76 77 <%block name="x"> 78 block 79 </%block> 80 """, 81 ) 82 83 def test_name_collision_blocks_nested_block(self): 84 assert_raises_message( 85 exceptions.CompileException, 86 "%def or %block named 'x' already exists in this template", 87 Template, 88 """ 89 <%block> 90 <%block name="x"> 91 block 92 </%block> 93 94 foob 95 96 <%block name="x"> 97 block 98 </%block> 99 </%block> 100 """, 101 ) 102 103 def test_name_collision_blocks_nested_def(self): 104 assert_raises_message( 105 exceptions.CompileException, 106 "Named block 'x' not allowed inside of def 'foo'", 107 Template, 108 """ 109 <%def name="foo()"> 110 <%block name="x"> 111 block 112 </%block> 113 114 foob 115 116 <%block name="x"> 117 block 118 </%block> 119 </%def> 120 """, 121 ) 122 123 def test_name_collision_block_def_toplevel(self): 124 assert_raises_message( 125 exceptions.CompileException, 126 "%def or %block named 'x' already exists in this template", 127 Template, 128 """ 129 <%block name="x"> 130 block 131 </%block> 132 133 foob 134 135 <%def name="x()"> 136 block 137 </%def> 138 """, 139 ) 140 141 def test_name_collision_def_block_toplevel(self): 142 assert_raises_message( 143 exceptions.CompileException, 144 "%def or %block named 'x' already exists in this template", 145 Template, 146 """ 147 <%def name="x()"> 148 block 149 </%def> 150 151 foob 152 153 <%block name="x"> 154 block 155 </%block> 156 157 """, 158 ) 159 160 def test_named_block_renders(self): 161 template = Template( 162 """ 163 above 164 <%block name="header"> 165 the header 166 </%block> 167 below 168 """ 169 ) 170 self._do_test( 171 template, ["above", "the header", "below"], filters=result_lines 172 ) 173 174 def test_inherited_block_no_render(self): 175 l = TemplateLookup() 176 l.put_string( 177 "index", 178 """ 179 <%inherit file="base"/> 180 <%block name="header"> 181 index header 182 </%block> 183 """, 184 ) 185 l.put_string( 186 "base", 187 """ 188 above 189 <%block name="header"> 190 the header 191 </%block> 192 193 ${next.body()} 194 below 195 """, 196 ) 197 self._do_test( 198 l.get_template("index"), 199 ["above", "index header", "below"], 200 filters=result_lines, 201 ) 202 203 def test_no_named_in_def(self): 204 assert_raises_message( 205 exceptions.CompileException, 206 "Named block 'y' not allowed inside of def 'q'", 207 Template, 208 """ 209 <%def name="q()"> 210 <%block name="y"> 211 </%block> 212 </%def> 213 """, 214 ) 215 216 def test_inherited_block_nested_both(self): 217 l = TemplateLookup() 218 l.put_string( 219 "index", 220 """ 221 <%inherit file="base"/> 222 <%block name="title"> 223 index title 224 </%block> 225 226 <%block name="header"> 227 index header 228 ${parent.header()} 229 </%block> 230 """, 231 ) 232 l.put_string( 233 "base", 234 """ 235 above 236 <%block name="header"> 237 base header 238 <%block name="title"> 239 the title 240 </%block> 241 </%block> 242 243 ${next.body()} 244 below 245 """, 246 ) 247 self._do_test( 248 l.get_template("index"), 249 ["above", "index header", "base header", "index title", "below"], 250 filters=result_lines, 251 ) 252 253 def test_inherited_block_nested_inner_only(self): 254 l = TemplateLookup() 255 l.put_string( 256 "index", 257 """ 258 <%inherit file="base"/> 259 <%block name="title"> 260 index title 261 </%block> 262 263 """, 264 ) 265 l.put_string( 266 "base", 267 """ 268 above 269 <%block name="header"> 270 base header 271 <%block name="title"> 272 the title 273 </%block> 274 </%block> 275 276 ${next.body()} 277 below 278 """, 279 ) 280 self._do_test( 281 l.get_template("index"), 282 ["above", "base header", "index title", "below"], 283 filters=result_lines, 284 ) 285 286 def test_noninherited_block_no_render(self): 287 l = TemplateLookup() 288 l.put_string( 289 "index", 290 """ 291 <%inherit file="base"/> 292 <%block name="some_thing"> 293 some thing 294 </%block> 295 """, 296 ) 297 l.put_string( 298 "base", 299 """ 300 above 301 <%block name="header"> 302 the header 303 </%block> 304 305 ${next.body()} 306 below 307 """, 308 ) 309 self._do_test( 310 l.get_template("index"), 311 ["above", "the header", "some thing", "below"], 312 filters=result_lines, 313 ) 314 315 def test_no_conflict_nested_one(self): 316 l = TemplateLookup() 317 l.put_string( 318 "index", 319 """ 320 <%inherit file="base"/> 321 <%block> 322 <%block name="header"> 323 inner header 324 </%block> 325 </%block> 326 """, 327 ) 328 l.put_string( 329 "base", 330 """ 331 above 332 <%block name="header"> 333 the header 334 </%block> 335 336 ${next.body()} 337 below 338 """, 339 ) 340 self._do_test( 341 l.get_template("index"), 342 ["above", "inner header", "below"], 343 filters=result_lines, 344 ) 345 346 def test_nested_dupe_names_raise(self): 347 assert_raises_message( 348 exceptions.CompileException, 349 "%def or %block named 'header' already exists in this template.", 350 Template, 351 """ 352 <%inherit file="base"/> 353 <%block name="header"> 354 <%block name="header"> 355 inner header 356 </%block> 357 </%block> 358 """, 359 ) 360 361 def test_two_levels_one(self): 362 l = TemplateLookup() 363 l.put_string( 364 "index", 365 """ 366 <%inherit file="middle"/> 367 <%block name="header"> 368 index header 369 </%block> 370 <%block> 371 index anon 372 </%block> 373 """, 374 ) 375 l.put_string( 376 "middle", 377 """ 378 <%inherit file="base"/> 379 <%block> 380 middle anon 381 </%block> 382 ${next.body()} 383 """, 384 ) 385 l.put_string( 386 "base", 387 """ 388 above 389 <%block name="header"> 390 the header 391 </%block> 392 393 ${next.body()} 394 below 395 """, 396 ) 397 self._do_test( 398 l.get_template("index"), 399 ["above", "index header", "middle anon", "index anon", "below"], 400 filters=result_lines, 401 ) 402 403 def test_filter(self): 404 template = Template( 405 """ 406 <%block filter="h"> 407 <html> 408 </%block> 409 """ 410 ) 411 self._do_test(template, ["<html>"], filters=result_lines) 412 413 def test_anon_in_named(self): 414 template = Template( 415 """ 416 <%block name="x"> 417 outer above 418 <%block> 419 inner 420 </%block> 421 outer below 422 </%block> 423 """ 424 ) 425 self._test_block_in_block(template) 426 427 def test_named_in_anon(self): 428 template = Template( 429 """ 430 <%block> 431 outer above 432 <%block name="x"> 433 inner 434 </%block> 435 outer below 436 </%block> 437 """ 438 ) 439 self._test_block_in_block(template) 440 441 def test_anon_in_anon(self): 442 template = Template( 443 """ 444 <%block> 445 outer above 446 <%block> 447 inner 448 </%block> 449 outer below 450 </%block> 451 """ 452 ) 453 self._test_block_in_block(template) 454 455 def test_named_in_named(self): 456 template = Template( 457 """ 458 <%block name="x"> 459 outer above 460 <%block name="y"> 461 inner 462 </%block> 463 outer below 464 </%block> 465 """ 466 ) 467 self._test_block_in_block(template) 468 469 def _test_block_in_block(self, template): 470 self._do_test( 471 template, 472 ["outer above", "inner", "outer below"], 473 filters=result_lines, 474 ) 475 476 def test_iteration(self): 477 t = Template( 478 """ 479 % for i in (1, 2, 3): 480 <%block>${i}</%block> 481 % endfor 482 """ 483 ) 484 self._do_test(t, ["1", "2", "3"], filters=result_lines) 485 486 def test_conditional(self): 487 t = Template( 488 """ 489 % if True: 490 <%block>true</%block> 491 % endif 492 493 % if False: 494 <%block>false</%block> 495 % endif 496 """ 497 ) 498 self._do_test(t, ["true"], filters=result_lines) 499 500 def test_block_overridden_by_def(self): 501 l = TemplateLookup() 502 l.put_string( 503 "index", 504 """ 505 <%inherit file="base"/> 506 <%def name="header()"> 507 inner header 508 </%def> 509 """, 510 ) 511 l.put_string( 512 "base", 513 """ 514 above 515 <%block name="header"> 516 the header 517 </%block> 518 519 ${next.body()} 520 below 521 """, 522 ) 523 self._do_test( 524 l.get_template("index"), 525 ["above", "inner header", "below"], 526 filters=result_lines, 527 ) 528 529 def test_def_overridden_by_block(self): 530 l = TemplateLookup() 531 l.put_string( 532 "index", 533 """ 534 <%inherit file="base"/> 535 <%block name="header"> 536 inner header 537 </%block> 538 """, 539 ) 540 l.put_string( 541 "base", 542 """ 543 above 544 ${self.header()} 545 <%def name="header()"> 546 the header 547 </%def> 548 549 ${next.body()} 550 below 551 """, 552 ) 553 self._do_test( 554 l.get_template("index"), 555 ["above", "inner header", "below"], 556 filters=result_lines, 557 ) 558 559 def test_block_args(self): 560 l = TemplateLookup() 561 l.put_string( 562 "caller", 563 """ 564 565 <%include file="callee" args="val1='3', val2='4'"/> 566 567 """, 568 ) 569 l.put_string( 570 "callee", 571 """ 572 <%page args="val1, val2"/> 573 <%block name="foob" args="val1, val2"> 574 foob, ${val1}, ${val2} 575 </%block> 576 """, 577 ) 578 self._do_test( 579 l.get_template("caller"), ["foob, 3, 4"], filters=result_lines 580 ) 581 582 def test_block_variables_contextual(self): 583 t = Template( 584 """ 585 <%block name="foob" > 586 foob, ${val1}, ${val2} 587 </%block> 588 """ 589 ) 590 self._do_test( 591 t, 592 ["foob, 3, 4"], 593 template_args={"val1": 3, "val2": 4}, 594 filters=result_lines, 595 ) 596 597 def test_block_args_contextual(self): 598 t = Template( 599 """ 600 <%page args="val1"/> 601 <%block name="foob" args="val1"> 602 foob, ${val1}, ${val2} 603 </%block> 604 """ 605 ) 606 self._do_test( 607 t, 608 ["foob, 3, 4"], 609 template_args={"val1": 3, "val2": 4}, 610 filters=result_lines, 611 ) 612 613 def test_block_pageargs_contextual(self): 614 t = Template( 615 """ 616 <%block name="foob"> 617 foob, ${pageargs['val1']}, ${pageargs['val2']} 618 </%block> 619 """ 620 ) 621 self._do_test( 622 t, 623 ["foob, 3, 4"], 624 template_args={"val1": 3, "val2": 4}, 625 filters=result_lines, 626 ) 627 628 def test_block_pageargs(self): 629 l = TemplateLookup() 630 l.put_string( 631 "caller", 632 """ 633 634 <%include file="callee" args="val1='3', val2='4'"/> 635 636 """, 637 ) 638 l.put_string( 639 "callee", 640 """ 641 <%block name="foob"> 642 foob, ${pageargs['val1']}, ${pageargs['val2']} 643 </%block> 644 """, 645 ) 646 self._do_test( 647 l.get_template("caller"), ["foob, 3, 4"], filters=result_lines 648 ) 649