comparison genshi/template/markup.py @ 703:3a4f2fd6f5e2 experimental-match-fastpaths

merge in trunk up through r818 - fundamentally changed the way MatchSet works, but actually is more consistent now
author aflett
date Mon, 31 Mar 2008 22:47:50 +0000
parents cea2e0d9ba28
children 4d2afb73d51b
comparison
equal deleted inserted replaced
701:ef60e59604c5 703:3a4f2fd6f5e2
224 stream.append((kind, data, pos)) 224 stream.append((kind, data, pos))
225 225
226 assert len(streams) == 1 226 assert len(streams) == 1
227 return streams[0] 227 return streams[0]
228 228
229 def _match(self, stream, ctxt, match_set=None): 229 def _match(self, stream, ctxt, match_set=None, **vars):
230 """Internal stream filter that applies any defined match templates 230 """Internal stream filter that applies any defined match templates
231 to the stream. 231 to the stream.
232 """ 232 """
233 if match_set is None: 233 if match_set is None:
234 match_set = ctxt._match_set 234 match_set = ctxt._match_set
261 for idx, match_template in enumerate(match_candidates): 261 for idx, match_template in enumerate(match_candidates):
262 262
263 (test, path, template, hints, namespaces, directives) = \ 263 (test, path, template, hints, namespaces, directives) = \
264 match_template 264 match_template
265 if test(event, namespaces, ctxt) is True: 265 if test(event, namespaces, ctxt) is True:
266 post_match_templates = \
267 match_set.after_template(match_template)
268
266 if 'match_once' in hints: 269 if 'match_once' in hints:
270
271 # need to save this before we nuke
272 # match_template from match_set
273 pre_match_templates = \
274 match_set.before_template(match_template, False)
275
276 # forcibly remove this template from this and
277 # all child match sets
267 match_set.remove(match_template) 278 match_set.remove(match_template)
268 del match_candidates[idx] 279 del match_candidates[idx]
269 idx -= 1 280 idx -= 1
281 else:
282 inclusive = True
283 if 'not_recursive' in hints:
284 inclusive=False
285 pre_match_templates = match_set.before_template(match_template, inclusive)
270 286
271 # Let the remaining match templates know about the event so 287 # Let the remaining match templates know about the event so
272 # they get a chance to update their internal state 288 # they get a chance to update their internal state
273 for test in [mt[0] for mt in match_candidates[idx + 1:]]: 289 for test in [mt[0] for mt in match_candidates[idx + 1:]]:
274 test(event, namespaces, ctxt, updateonly=True) 290 test(event, namespaces, ctxt, updateonly=True)
275 291
276 # Consume and store all events until an end event 292 # Consume and store all events until an end event
277 # corresponding to this start event is encountered 293 # corresponding to this start event is encountered
278 inner = _strip(stream) 294 inner = _strip(stream)
279 if 'match_once' not in hints \ 295 if pre_match_templates:
280 and 'not_recursive' not in hints: 296 inner = self._match(inner, ctxt, pre_match_templates)
281 inner = self._match(inner, ctxt, 297 content = self._include(chain([event], inner, tail), ctxt)
282 MatchSet.single_match(match_template)) 298 if 'not_buffered' not in hints:
283 content = list(self._include(chain([event], inner, tail), 299 content = list(content)
284 ctxt))
285 300
286 # Now tell all the match templates about the 301 # Now tell all the match templates about the
287 # END event (tail[0]) 302 # END event (tail[0])
288 for test in [mt[0] for mt in match_candidates]: 303 if tail:
289 test(tail[0], namespaces, ctxt, updateonly=True) 304 for test in [mt[0] for mt in match_candidates]:
305 test(tail[0], namespaces, ctxt, updateonly=True)
290 306
291 # Make the select() function available in the body of the 307 # Make the select() function available in the body of the
292 # match template 308 # match template
293 def select(path): 309 def select(path):
294 return Stream(content).select(path, namespaces, ctxt) 310 return Stream(content).select(path, namespaces, ctxt)
295 ctxt.push(dict(select=select)) 311 vars = dict(select=select)
296 312
297 # Recursively process the output 313 # Recursively process the output
298 template = _apply_directives(template, ctxt, directives) 314 template = _apply_directives(template, directives, ctxt,
299 remaining = match_set 315 **vars)
300 if 'match_once' not in hints: 316 for event in self._match(
301 # match has not been removed, so we need an 317 self._exec(
302 # exclusion matchset 318 self._eval(
303 remaining = match_set.with_exclusion(match_template) 319 self._flatten(template, ctxt, **vars),
304 320 ctxt, **vars),
305 body = self._exec(self._eval(self._flatten(template, ctxt), 321 ctxt, **vars),
306 ctxt), ctxt) 322 ctxt, post_match_templates,
307 for event in self._match(body, ctxt, remaining): 323 **vars):
308 yield event 324 yield event
309 325
310 ctxt.pop()
311 break 326 break
312 327
313 else: # no matches 328 else: # no matches
314 yield event 329 yield event
Copyright (C) 2012-2017 Edgewall Software