Edgewall Software

Ticket #431: py-else-r1162.diff

File py-else-r1162.diff, 4.4 KB (added by hodgestar, 12 years ago)

Initial outline of implementation (from Eoghan's email with a little clean up by me).

  • genshi/template/base.py

     
    128128        self.push = self.frames.appendleft
    129129        self._match_templates = []
    130130        self._choice_stack = []
     131        self._else_stack = []
    131132
    132133        # Helper functions for use in expressions
    133134        def defined(name):
  • genshi/template/markup.py

     
    5151                  ('otherwise', OtherwiseDirective),
    5252                  ('for', ForDirective),
    5353                  ('if', IfDirective),
     54                  ('else', ElseDirective),
    5455                  ('choose', ChooseDirective),
    5556                  ('with', WithDirective),
    5657                  ('replace', ReplaceDirective),
  • genshi/template/directives.py

     
    2121                                 _ast, _parse
    2222
    2323__all__ = ['AttrsDirective', 'ChooseDirective', 'ContentDirective',
    24            'DefDirective', 'ForDirective', 'IfDirective', 'MatchDirective',
    25            'OtherwiseDirective', 'ReplaceDirective', 'StripDirective',
    26            'WhenDirective', 'WithDirective']
     24           'DefDirective', 'ForDirective', 'IfDirective', 'ElseDirective',
     25           'MatchDirective', 'OtherwiseDirective', 'ReplaceDirective',
     26           'StripDirective', 'WhenDirective', 'WithDirective']
    2727__docformat__ = 'restructuredtext en'
    2828
    2929
     
    378378class IfDirective(Directive):
    379379    """Implementation of the ``py:if`` template directive for conditionally
    380380    excluding elements from being output.
    381    
     381
    382382    >>> from genshi.template import MarkupTemplate
    383383    >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
    384384    ...   <b py:if="foo">${bar}</b>
     
    387387    <div>
    388388      <b>Hello</b>
    389389    </div>
     390
     391    If the ``py:if`` directive contains a ``py:else`` directive,
     392    the contents of the else block will be output if the condition
     393    evaluates to ``False``
     394
     395    >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/"
     396    ...   py:if="False">
     397    ...   Will not be output
     398    ...   <py:else>Will be output</py:else>
     399    ... </div>''')
     400    >>> print(tmpl.generate())
     401    Will be output
     402
     403    Behavior is undefined if a ``py:else`` block exists outside a
     404    ``py:if`` block.
    390405    """
    391406    __slots__ = []
    392407
     
    401416        value = _eval_expr(self.expr, ctxt, vars)
    402417        if value:
    403418            return _apply_directives(stream, directives, ctxt, vars)
     419        else:
     420
     421            def _generate():
     422                previous = stream.next()
     423                for event in stream:
     424                    if (previous[0] == 'SUB' and
     425                        isinstance(previous[1][0][0], ElseDirective)):
     426                        ctxt._else_stack.append(previous[1][0][0])
     427                        yield previous
     428                    previous = event
     429            return _apply_directives(_generate(), directives, ctxt, vars)
    404430        return []
    405431
    406432
     433class ElseDirective(Directive):
     434    """Implementation of the ``py:else`` directive for nesting in a parent with
     435    the ``py:if`` directive.
     436
     437    See the documentation of the `IfDirective` for usage.
     438    """
     439    __slots__ = ['filename']
     440
     441    def __init__(self, value, template, namespaces=None, lineno=-1, offset=-1):
     442        Directive.__init__(self, value, template, namespaces, lineno, offset)
     443        self.filename = template.filepath
     444
     445    def __call__(self, stream, directives, ctxt, **vars):
     446        info = ctxt._else_stack and ctxt._else_stack[-1]
     447        if not info:
     448            raise TemplateRuntimeError('"else" directives can only be used '
     449                                       'inside an "if" directive',
     450                                       self.filename, *(stream.next())[2][1:])
     451        if ctxt._else_stack and ctxt._else_stack[-1] is self:
     452            ctxt._else_stack.pop()
     453            return _apply_directives(stream, directives, ctxt, vars)
     454        else:
     455            return []
     456
     457
    407458class MatchDirective(Directive):
    408459    """Implementation of the ``py:match`` template directive.
    409460