Edgewall Software

Ticket #396: select.patch

File select.patch, 9.5 KB (added by Carsten Klein <carsten.klein@…>, 6 years ago)

Still some issues here, moved addition of the select function outside of the loop, as it was added to the variables for each test in a given match template

  • markup.py

     
    1818from genshi.core import Attrs, Markup, Namespace, Stream, StreamEventKind
    1919from genshi.core import START, END, START_NS, END_NS, TEXT, PI, COMMENT
    2020from genshi.input import XMLParser
    21 from genshi.template.base import BadDirectiveError, Template, \
    22                                  TemplateSyntaxError, _apply_directives, \
    23                                  EXEC, INCLUDE, SUB
     21from genshi.template.base import Template, TemplateSyntaxError, \
     22                                 _apply_directives, EXEC, INCLUDE, SUB
    2423from genshi.template.eval import Suite
     24from genshi.template.directives import DirectivesLibraryManager, \
     25                                       UnknownDirectiveError
    2526from genshi.template.interpolation import interpolate
    26 from genshi.template.directives import *
    2727from genshi.template.text import NewTextTemplate
    2828
    2929__all__ = ['MarkupTemplate']
     
    4242    </ul>
    4343    """
    4444
    45     DIRECTIVE_NAMESPACE = 'http://genshi.edgewall.org/'
    4645    XINCLUDE_NAMESPACE = 'http://www.w3.org/2001/XInclude'
    4746
    48     directives = [('def', DefDirective),
    49                   ('match', MatchDirective),
    50                   ('when', WhenDirective),
    51                   ('otherwise', OtherwiseDirective),
    52                   ('for', ForDirective),
    53                   ('if', IfDirective),
    54                   ('choose', ChooseDirective),
    55                   ('with', WithDirective),
    56                   ('replace', ReplaceDirective),
    57                   ('content', ContentDirective),
    58                   ('attrs', AttrsDirective),
    59                   ('strip', StripDirective)]
    6047    serializer = 'xml'
    6148    _number_conv = Markup
    6249
    6350    def __init__(self, source, filepath=None, filename=None, loader=None,
    64                  encoding=None, lookup='strict', allow_exec=True):
     51                 encoding=None, lookup='strict', allow_exec=True,
     52                 directives_library_manager=None):
    6553        Template.__init__(self, source, filepath=filepath, filename=filename,
    6654                          loader=loader, encoding=encoding, lookup=lookup,
    67                           allow_exec=allow_exec)
    68         self.add_directives(self.DIRECTIVE_NAMESPACE, self)
     55                          allow_exec=allow_exec, directives_library_manager= \
     56                          directives_library_manager)
     57        self._stream = self._extract_directives(self._stream)
    6958
    7059    def _init_filters(self):
    7160        Template._init_filters(self)
     
    111100
    112101        return stream
    113102
    114     def _extract_directives(self, stream, namespace, factory):
     103    def _extract_directives(self, stream):
    115104        depth = 0
    116105        dirmap = {} # temporary mapping of directives to elements
    117106        new_stream = []
    118107        ns_prefix = {} # namespace prefixes in use
    119108
     109        library = self.directives_library
     110
    120111        for kind, data, pos in stream:
    121112
    122113            if kind is START:
     
    124115                directives = []
    125116                strip = False
    126117
    127                 if tag.namespace == namespace:
    128                     cls = factory.get_directive(tag.localname)
     118                if library.defines_namespace(tag.namespace):
     119                    cls = library.get_directive(tag.localname,
     120                                                namespace=tag.namespace)
    129121                    if cls is None:
    130                         raise BadDirectiveError(tag.localname,
    131                                                 self.filepath, pos[1])
     122                        raise UnknownDirectiveError(tag.localname,
     123                                                    self.filepath, pos[1])
     124# FIXME:axn arguments to directives should be in the namespace of
     125# the directive, alternatively one may use no namespace at all
     126# for when using namespaces, must make sure that no directive of that
     127# namespace is being defined in the library
    132128                    args = dict([(name.localname, value) for name, value
    133129                                 in attrs if not name.namespace])
    134                     directives.append((factory.get_directive_index(cls), cls,
    135                                        args, ns_prefix.copy(), pos))
     130
     131                    directives.append((
     132                        library.get_directive_priority(tag.localname,
     133                                                       namespace=
     134                                                       tag.namespace),
     135                                                       cls, args,
     136                                                       ns_prefix.copy(),
     137                                                       pos))
    136138                    strip = True
    137139
    138140                new_attrs = []
    139141                for name, value in attrs:
    140                     if name.namespace == namespace:
    141                         cls = factory.get_directive(name.localname)
     142                    if library.defines_namespace(name.namespace):
     143                        cls = library.get_directive(name.localname,
     144                                                    namespace=name.namespace)
    142145                        if cls is None:
    143                             raise BadDirectiveError(name.localname,
    144                                                     self.filepath, pos[1])
     146                            raise UnknownDirectiveError(name.localname,
     147                                                        self.filepath, pos[1])
    145148                        if type(value) is list and len(value) == 1:
    146149                            value = value[0][1]
    147                         directives.append((factory.get_directive_index(cls),
    148                                            cls, value, ns_prefix.copy(), pos))
     150                        directives.append((
     151                            library.get_directive_priority(name.localname,
     152                                                           namespace=
     153                                                           name.namespace),
     154                                                           cls, value,
     155                                                           ns_prefix.copy(),
     156                                                           pos))
    149157                    else:
    150158                        new_attrs.append((name, value))
    151159                new_attrs = Attrs(new_attrs)
    152160
    153161                if directives:
    154                     directives.sort()
     162                    #directives.sort()
    155163                    dirmap[(depth, tag)] = (directives, len(new_stream),
    156164                                            strip)
    157165
     
    176184
    177185            elif kind is SUB:
    178186                directives, substream = data
    179                 substream = self._extract_directives(substream, namespace,
    180                                                      factory)
     187                substream = self._extract_directives(substream)
    181188
    182189                if len(substream) == 1 and substream[0][0] is SUB:
    183190                    added_directives, substream = substream[0][1]
     
    190197                # directives
    191198                prefix, uri = data
    192199                ns_prefix[prefix] = uri
    193                 if uri != namespace:
     200                if not library.defines_namespace(uri):
    194201                    new_stream.append((kind, data, pos))
    195202
    196203            elif kind is END_NS:
    197204                uri = ns_prefix.pop(data, None)
    198                 if uri and uri != namespace:
     205                if uri and not library.defines_namespace(uri):
    199206                    new_stream.append((kind, data, pos))
    200207
    201208            else:
     
    291298            self._extract_includes(self._interpolate_attrs(stream))
    292299        )
    293300
    294     def add_directives(self, namespace, factory):
    295         """Register a custom `DirectiveFactory` for a given namespace.
    296        
    297         :param namespace: the namespace URI
    298         :type namespace: `basestring`
    299         :param factory: the directive factory to register
    300         :type factory: `DirectiveFactory`
    301         :since: version 0.6
    302         """
    303         assert not self._prepared, 'Too late for adding directives, ' \
    304                                    'template already prepared'
    305         self._stream = self._extract_directives(self._stream, namespace,
    306                                                 factory)
    307 
    308301    def _match(self, stream, ctxt, start=0, end=None, **vars):
    309302        """Internal stream filter that applies any defined match templates
    310303        to the stream.
     
    327320                    append(event)
    328321                    break
    329322
     323        # Make the select() function available in the body of the
     324        # match template
     325        selected = [False]
     326        def select(path):
     327            selected[0] = True
     328            return content.select(path, namespaces, ctxt)
     329        vars['select'] = select
     330
    330331        for event in stream:
    331332
    332333            # We (currently) only care about start and end events for matching
     
    365366                        content = list(content)
    366367                    content = Stream(content)
    367368
    368                     # Make the select() function available in the body of the
    369                     # match template
    370                     selected = [False]
    371                     def select(path):
    372                         selected[0] = True
    373                         return content.select(path, namespaces, ctxt)
    374                     vars = dict(select=select)
    375 
    376369                    # Recursively process the output
    377370                    template = _apply_directives(template, directives, ctxt,
    378371                                                 vars)