Edgewall Software

Ticket #396: select_added_too_late.patch

File select_added_too_late.patch, 9.9 KB (added by Carsten Klein <carsten.klein@…>, 4 years ago)
  • genshi/template/inline.py

     
    7979    return '{%s}' % ', '.join(buf) 
    8080 
    8181 
     82# represents basically a symbol table 
     83class Context(object): 
     84 
     85    def __init__(self): 
     86        self.qnames = [] 
     87        self.attributes = {} 
     88        self.expressions = [] 
     89        self.macros = {} 
     90        self.paths = [] 
     91        self.suites = [] 
     92        self.variables = {} 
     93        self.last_event = None 
     94 
     95    def declare_attr(self, qname, value): 
     96        pass 
     97 
     98    def declare_expression(self, expr): 
     99        pass 
     100 
     101    def declare_macro(self, name, macro): 
     102        pass 
     103 
     104    def declare_path(self, path): 
     105        pass 
     106 
     107    def declare_qname(self, qname): 
     108        pass 
     109 
     110    def declare_suite(self, suite): 
     111        pass 
     112 
     113    def declare_variable(self, name, expr): 
     114        pass 
     115 
     116 
     117# Stream 
     118class StreamProcessor(object): 
     119 
     120    def __init__(self): 
     121        self.visitors = [] 
     122        self.visitors.append(EndEventVisitor()) 
     123        self.visitors.append(ExecEventVisitor()) 
     124        self.visitors.append(IncludeEventVisitor()) 
     125        self.visitors.append(StartEventVisitor()) 
     126        self.visitors.append(SubstreamEventVisitor()) 
     127 
     128    def process(self, stream, context): 
     129        for kind, data, pos in stream: 
     130            context.last_event = (kind, data, pos) 
     131            for visitor in visitors: 
     132                if visitor.can_visit(kind): 
     133                    visitor.visit(kind, data, pos, context) 
     134                    break 
     135 
     136 
     137# Stream Events 
     138class StreamEventVisitor(object): 
     139 
     140    #@abstractmethod 
     141    def can_visit(self, kind): 
     142        pass 
     143 
     144    #@abstractmethod 
     145    def visit(self, kind, data, pos, context): 
     146        pass 
     147 
     148 
     149class EndEventVisitor(StreamEventVisitor): 
     150 
     151    def can_visit(self, kind): 
     152        return kind is END 
     153 
     154    def visit(self, kind, data, pos, context): 
     155        pass 
     156 
     157 
     158class ExecEventVisitor(StreamEventVisitor): 
     159 
     160    def can_visit(self, kind): 
     161        return kind is EXEC 
     162 
     163    def visit(self, kind, data, pos, context): 
     164        pass 
     165 
     166 
     167class IncludeEventVisitor(StreamEventVisitor): 
     168 
     169    def can_visit(self, kind): 
     170        return kind is INCLUDE 
     171 
     172    def visit(self, kind, data, pos, context): 
     173        pass 
     174 
     175 
     176class StartEventVisitor(StreamEventVisitor): 
     177 
     178    def can_visit(self, kind): 
     179        return kind is START 
     180 
     181    def visit(self, kind, data, pos, context): 
     182        pass 
     183 
     184 
     185class SubstreamEventVisitor(StreamEventVisitor): 
     186 
     187    def __init__(self): 
     188        self.visitors = [] 
     189        self.visitors.append(AttrsDirectiveVisitor()) 
     190        self.visitors.append(ChooseDirectiveVisitor()) 
     191        self.visitors.append(ContentDirectiveVisitor()) 
     192        self.visitors.append(DefDirectiveVisitor()) 
     193        self.visitors.append(ForDirectiveVisitor()) 
     194        self.visitors.append(IfDirectiveVisitor()) 
     195        self.visitors.append(MatchDirectiveVisitor()) 
     196        self.visitors.append(OtherwiseDirectiveVisitor()) 
     197        self.visitors.append(ReplaceDirectiveVisitor()) 
     198        self.visitors.append(StripDirectiveVisitor()) 
     199        self.visitors.append(WhenDirectiveVisitor()) 
     200        self.visitors.append(WithDirectiveVisitor()) 
     201 
     202    def can_visit(self, kind): 
     203        return kind is SUB 
     204 
     205    def visit(self, kind, data, pos, context): 
     206        directives, substream = data 
     207 
     208        for directive in directives: 
     209            for visitor in self.visitors: 
     210                if visitor.can_visit(directive): 
     211                    visitor.visit(directive, substream, context) 
     212                    break 
     213 
     214        # recursively process the substreams 
     215        processor = StreamProcessor() 
     216        processor.process(substream, context) 
     217 
     218 
     219# Directives 
     220 
     221class DirectiveVisitor(object): 
     222 
     223    #@abstractmethod 
     224    def can_vist(self, directive): 
     225        pass 
     226 
     227    #@abstractmethod 
     228    def visit(self, directive, substream, context): 
     229        pass 
     230 
     231 
     232class AttrsDirectiveVisitor(DirectiveVisitor): 
     233 
     234    def can_visit(self, kind): 
     235        return isinstance(directive, AttrsDirective) 
     236 
     237    def visit(self, directive, substream, context): 
     238        pass 
     239 
     240 
     241class ChooseDirectiveVisitor(DirectiveVisitor): 
     242 
     243    def can_visit(self, kind): 
     244        return isinstance(directive, ChooseDirective) 
     245 
     246    def visit(self, directive, substream, context): 
     247        pass 
     248 
     249 
     250class ContentDirectiveVisitor(DirectiveVisitor): 
     251 
     252    def can_visit(self, kind): 
     253        return isinstance(directive, ContentDirective) 
     254 
     255    def visit(self, directive, substream, context): 
     256        pass 
     257 
     258 
     259class DefDirectiveVisitor(DirectiveVisitor): 
     260 
     261    def can_visit(self, kind): 
     262        return isinstance(directive, DefDirective) 
     263 
     264    def visit(self, directive, substream, context): 
     265        pass 
     266 
     267 
     268class ForDirectiveVisitor(DirectiveVisitor): 
     269 
     270    def can_visit(self, kind): 
     271        return isinstance(directive, ForDirective) 
     272 
     273    def visit(self, directive, substream, context): 
     274        pass 
     275 
     276 
     277class IfDirectiveVisitor(DirectiveVisitor): 
     278 
     279    def can_visit(self, kind): 
     280        return isinstance(directive, IfDirective) 
     281 
     282    def visit(self, directive, substream, context): 
     283 
     284        if directive.expr: 
     285            context.declare_expression( directive.expr ) 
     286 
     287 
     288class MatchDirectiveVisitor(DirectiveVisitor): 
     289 
     290    def can_visit(self, kind): 
     291        return isinstance(directive, MatchDirective) 
     292 
     293    def visit(self, directive, substream, context): 
     294 
     295        if directive.path: 
     296            context.declare_path( directive.path ) 
     297 
     298 
     299class OtherwiseDirectiveVisitor(DirectiveVisitor): 
     300 
     301    def can_visit(self, kind): 
     302        return isinstance(directive, OtherwiseDirective) 
     303 
     304    def visit(self, directive, substream, context): 
     305        pass 
     306 
     307 
     308class ReplaceDirectiveVisitor(DirectiveVisitor): 
     309 
     310    def can_visit(self, kind): 
     311        return isinstance(directive, ReplaceDirective) 
     312 
     313    def visit(self, directive, substream, context): 
     314        pass 
     315 
     316 
     317class StripDirectiveVisitor(DirectiveVisitor): 
     318 
     319    def can_visit(self, kind): 
     320        return isinstance(directive, StripDirective) 
     321 
     322    def visit(self, directive, substream, context): 
     323        # FIXME problem here, strip strips the current element when true,  
     324        # which is already accomplished by this, 
     325        # however, if strip resolves to false, then the original element 
     326        # in the stream must be preserved, which is currently not supported 
     327        # by this, unless context would provide something like last_event 
     328        pass 
     329 
     330 
     331class WhenDirectiveVisitor(DirectiveVisitor): 
     332 
     333    def can_visit(self, kind): 
     334        return isinstance(directive, WhenDirective) 
     335 
     336    def visit(self, directive, substream, context): 
     337 
     338        if directive.expr: 
     339            context.declare_expr(directive.expr) 
     340        else: 
     341            raise Error() 
     342 
     343 
     344class WithDirectiveVisitor(DirectiveVisitor): 
     345 
     346    def can_visit(self, kind): 
     347        return isinstance(directive, WithDirective) 
     348 
     349    def visit(self, directive, substream, context): 
     350 
     351        if directive.vars: 
     352            for var in directive.vars: 
     353                context.declare_variable(var) 
     354 
     355 
    82356def inline(template): 
    83357    w = CodeWriter() 
    84358 
     
    118392                directives, substream = data 
    119393                for directive in directives: 
    120394 
     395                    # IfDirective, WhenDirective, OtherwiseDirective, ChooseDirective 
    121396                    if directive.expr: 
    122397                        yield 'E', directive.expr, directive.expr 
    123398 
     399                    # WithDirective 
    124400                    elif hasattr(directive, 'vars'): 
    125401                        for _, expr in directive.vars: 
    126402                            yield 'E', expr, expr 
    127403 
     404                    # MatchDirective 
    128405                    elif hasattr(directive, 'path') and directive.path: 
    129406                        yield 'P', directive.path, directive.path 
    130407 
     
    274551    for line in _generate(template.stream): 
    275552        yield line 
    276553 
     554    # THINK must also remove macro functions at end of compiled template? 
     555    # declared macros are generally visible on a global scope, therefore 
     556    # they should be kept in context 
     557    #if defs: 
     558    #    yield w() 
     559    #    yield w('pop()') 
     560    #    yield w() 
    277561 
    278562if __name__ == '__main__': 
    279563    import timeit 
     
    297581        <span py:replace="item + 1">NUM</span> 
    298582      </li> 
    299583    </ul> 
     584    <div id="foo">foo</div> 
     585    <div id="bar">bar</div> 
    300586 </body> 
    301587</html>""" 
    302588 
  • genshi/template/markup.py

     
    343343                        del match_templates[idx] 
    344344                        idx -= 1 
    345345 
     346                    # Make the select() function available in the body of the 
     347                    # match template 
     348                    selected = [False] 
     349                    def select(path): 
     350                        selected[0] = True 
     351                        return content.select(path, namespaces, ctxt) 
     352                    vars = dict(select=select) 
     353 
    346354                    # Let the remaining match templates know about the event so 
    347355                    # they get a chance to update their internal state 
    348356                    for test in [mt[0] for mt in match_templates[idx + 1:]]: 
     
    362370                        content = list(content) 
    363371                    content = Stream(content) 
    364372 
    365                     # Make the select() function available in the body of the 
    366                     # match template 
    367                     selected = [False] 
    368                     def select(path): 
    369                         selected[0] = True 
    370                         return content.select(path, namespaces, ctxt) 
    371                     vars = dict(select=select) 
    372  
    373373                    # Recursively process the output 
    374374                    template = _apply_directives(template, directives, ctxt, 
    375375                                                 vars)