Mercurial > genshi > mirror
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.""" |