Mercurial > genshi > genshi-test
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 |