comparison markup/template.py @ 44:436e30c8420b trunk

implement `py:choose/when/otherwise` directives for conditionally selecting one of several blocks
author mgood
date Mon, 03 Jul 2006 23:55:03 +0000
parents ee669cb9cccc
children a5d585dd38c4
comparison
equal deleted inserted replaced
43:e03b77726756 44:436e30c8420b
501 else: 501 else:
502 for event in stream: 502 for event in stream:
503 yield event 503 yield event
504 504
505 505
506 class ChooseDirective(Directive):
507 """Implementation of the `py:choose` directive for conditionally selecting
508 one of several body elements to display.
509
510 If the `py:choose` expression is empty the expressions of nested `py:when`
511 directives are tested for truth. The first true `py:when` body is output.
512
513 >>> ctxt = Context()
514 >>> tmpl = Template('''<div xmlns:py="http://purl.org/kid/ns#"
515 ... py:choose="">
516 ... <span py:when="0 == 1">0</span>
517 ... <span py:when="1 == 1">1</span>
518 ... </div>''')
519 >>> print tmpl.generate(ctxt)
520 <div>
521 <span>1</span>
522 </div>
523
524 If multiple `py:when` bodies match only the first is output.
525 >>> tmpl = Template('''<div xmlns:py="http://purl.org/kid/ns#"
526 ... py:choose="">
527 ... <span py:when="1 == 1">1</span>
528 ... <span py:when="2 == 2">2</span>
529 ... </div>''')
530 >>> print tmpl.generate(ctxt)
531 <div>
532 <span>1</span>
533 </div>
534
535 If the `py:choose` directive contains an expression, the nested `py:when`
536 directives are tested for equality to the `py:choose` expression.
537 >>> tmpl = Template('''<div xmlns:py="http://purl.org/kid/ns#"
538 ... py:choose="2">
539 ... <span py:when="1">1</span>
540 ... <span py:when="2">2</span>
541 ... </div>''')
542 >>> print tmpl.generate(ctxt)
543 <div>
544 <span>2</span>
545 </div>
546
547 If no `py:when` directive is matched then the fallback directive
548 `py:otherwise` will be used.
549 >>> tmpl = Template('''<div xmlns:py="http://purl.org/kid/ns#"
550 ... py:choose="">
551 ... <span py:when="False">hidden</span>
552 ... <span py:otherwise="">hello</span>
553 ... </div>''')
554 >>> print tmpl.generate(ctxt)
555 <div>
556 <span>hello</span>
557 </div>
558
559 `py:choose` blocks can be nested:
560 >>> tmpl = Template('''<div xmlns:py="http://purl.org/kid/ns#"
561 ... py:choose="1">
562 ... <div py:when="1" py:choose="3">
563 ... <span py:when="2">2</span>
564 ... <span py:when="3">3</span>
565 ... </div>
566 ... </div>''')
567 >>> print tmpl.generate(ctxt)
568 <div>
569 <div>
570 <span>3</span>
571 </div>
572 </div>
573
574 Behavior is undefined if a `py:choose` block contains content outside a
575 `py:when` or `py:otherwise` block. Behavior is also undefined if a
576 `py:otherwise` occurs before `py:when` blocks.
577 """
578
579 def __call__(self, stream, ctxt):
580 if self.expr:
581 self.value = self.expr.evaluate(ctxt)
582 self.matched = False
583 ctxt.push(__choose=self)
584 for event in stream:
585 yield event
586 ctxt.pop()
587
588
589 class WhenDirective(Directive):
590 """Implementation of the `py:when` directive for nesting in a parent with
591 the `py:choose` directive. See the documentation of `py:choose` for
592 usage.
593 """
594 def __call__(self, stream, ctxt):
595 choose = ctxt['__choose']
596 if choose.matched:
597 return []
598 value = self.expr.evaluate(ctxt)
599 try:
600 if value == choose.value:
601 choose.matched = True
602 return stream
603 except AttributeError:
604 if value:
605 choose.matched = True
606 return stream
607 return []
608
609
610 class OtherwiseDirective(Directive):
611 """Implementation of the `py:otherwise` directive for nesting in a parent
612 with the `py:choose` directive. See the documentation of `py:choose` for
613 usage.
614 """
615 def __call__(self, stream, ctxt):
616 choose = ctxt['__choose']
617 if choose.matched:
618 return []
619 choose.matched = True
620 return stream
621
622
506 class Template(object): 623 class Template(object):
507 """Can parse a template and transform it into the corresponding output 624 """Can parse a template and transform it into the corresponding output
508 based on context data. 625 based on context data.
509 """ 626 """
510 NAMESPACE = Namespace('http://purl.org/kid/ns#') 627 NAMESPACE = Namespace('http://purl.org/kid/ns#')
517 ('for', ForDirective), 634 ('for', ForDirective),
518 ('if', IfDirective), 635 ('if', IfDirective),
519 ('replace', ReplaceDirective), 636 ('replace', ReplaceDirective),
520 ('content', ContentDirective), 637 ('content', ContentDirective),
521 ('attrs', AttrsDirective), 638 ('attrs', AttrsDirective),
522 ('strip', StripDirective)] 639 ('strip', StripDirective),
640 ('choose', ChooseDirective),
641 ('when', WhenDirective),
642 ('otherwise', OtherwiseDirective)]
523 _dir_by_name = dict(directives) 643 _dir_by_name = dict(directives)
524 _dir_order = [directive[1] for directive in directives] 644 _dir_order = [directive[1] for directive in directives]
525 645
526 def __init__(self, source, basedir=None, filename=None): 646 def __init__(self, source, basedir=None, filename=None):
527 """Initialize a template from either a string or a file-like object.""" 647 """Initialize a template from either a string or a file-like object."""
Copyright (C) 2012-2017 Edgewall Software