Ticket #396: select.patch
| File select.patch, 9.5 KB (added by Carsten Klein <carsten.klein@…>, 13 years ago) |
|---|
-
markup.py
18 18 from genshi.core import Attrs, Markup, Namespace, Stream, StreamEventKind 19 19 from genshi.core import START, END, START_NS, END_NS, TEXT, PI, COMMENT 20 20 from genshi.input import XMLParser 21 from genshi.template.base import BadDirectiveError, Template, \ 22 TemplateSyntaxError, _apply_directives, \ 23 EXEC, INCLUDE, SUB 21 from genshi.template.base import Template, TemplateSyntaxError, \ 22 _apply_directives, EXEC, INCLUDE, SUB 24 23 from genshi.template.eval import Suite 24 from genshi.template.directives import DirectivesLibraryManager, \ 25 UnknownDirectiveError 25 26 from genshi.template.interpolation import interpolate 26 from genshi.template.directives import *27 27 from genshi.template.text import NewTextTemplate 28 28 29 29 __all__ = ['MarkupTemplate'] … … 42 42 </ul> 43 43 """ 44 44 45 DIRECTIVE_NAMESPACE = 'http://genshi.edgewall.org/'46 45 XINCLUDE_NAMESPACE = 'http://www.w3.org/2001/XInclude' 47 46 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)]60 47 serializer = 'xml' 61 48 _number_conv = Markup 62 49 63 50 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): 65 53 Template.__init__(self, source, filepath=filepath, filename=filename, 66 54 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) 69 58 70 59 def _init_filters(self): 71 60 Template._init_filters(self) … … 111 100 112 101 return stream 113 102 114 def _extract_directives(self, stream , namespace, factory):103 def _extract_directives(self, stream): 115 104 depth = 0 116 105 dirmap = {} # temporary mapping of directives to elements 117 106 new_stream = [] 118 107 ns_prefix = {} # namespace prefixes in use 119 108 109 library = self.directives_library 110 120 111 for kind, data, pos in stream: 121 112 122 113 if kind is START: … … 124 115 directives = [] 125 116 strip = False 126 117 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) 129 121 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 132 128 args = dict([(name.localname, value) for name, value 133 129 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)) 136 138 strip = True 137 139 138 140 new_attrs = [] 139 141 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) 142 145 if cls is None: 143 raise BadDirectiveError(name.localname,144 self.filepath, pos[1])146 raise UnknownDirectiveError(name.localname, 147 self.filepath, pos[1]) 145 148 if type(value) is list and len(value) == 1: 146 149 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)) 149 157 else: 150 158 new_attrs.append((name, value)) 151 159 new_attrs = Attrs(new_attrs) 152 160 153 161 if directives: 154 directives.sort()162 #directives.sort() 155 163 dirmap[(depth, tag)] = (directives, len(new_stream), 156 164 strip) 157 165 … … 176 184 177 185 elif kind is SUB: 178 186 directives, substream = data 179 substream = self._extract_directives(substream, namespace, 180 factory) 187 substream = self._extract_directives(substream) 181 188 182 189 if len(substream) == 1 and substream[0][0] is SUB: 183 190 added_directives, substream = substream[0][1] … … 190 197 # directives 191 198 prefix, uri = data 192 199 ns_prefix[prefix] = uri 193 if uri != namespace:200 if not library.defines_namespace(uri): 194 201 new_stream.append((kind, data, pos)) 195 202 196 203 elif kind is END_NS: 197 204 uri = ns_prefix.pop(data, None) 198 if uri and uri != namespace:205 if uri and not library.defines_namespace(uri): 199 206 new_stream.append((kind, data, pos)) 200 207 201 208 else: … … 291 298 self._extract_includes(self._interpolate_attrs(stream)) 292 299 ) 293 300 294 def add_directives(self, namespace, factory):295 """Register a custom `DirectiveFactory` for a given namespace.296 297 :param namespace: the namespace URI298 :type namespace: `basestring`299 :param factory: the directive factory to register300 :type factory: `DirectiveFactory`301 :since: version 0.6302 """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 308 301 def _match(self, stream, ctxt, start=0, end=None, **vars): 309 302 """Internal stream filter that applies any defined match templates 310 303 to the stream. … … 327 320 append(event) 328 321 break 329 322 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 330 331 for event in stream: 331 332 332 333 # We (currently) only care about start and end events for matching … … 365 366 content = list(content) 366 367 content = Stream(content) 367 368 368 # Make the select() function available in the body of the369 # match template370 selected = [False]371 def select(path):372 selected[0] = True373 return content.select(path, namespaces, ctxt)374 vars = dict(select=select)375 376 369 # Recursively process the output 377 370 template = _apply_directives(template, directives, ctxt, 378 371 vars)
