Mercurial > genshi > mirror
comparison genshi/template/markup.py @ 700:08f22328303d trunk
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
author | cmlenz |
---|---|
date | Fri, 28 Mar 2008 14:14:26 +0000 |
parents | 07e3f6f0ef57 |
children | fc6d9d2a3527 |
comparison
equal
deleted
inserted
replaced
699:cfe3b4f02d77 | 700:08f22328303d |
---|---|
223 stream.append((kind, data, pos)) | 223 stream.append((kind, data, pos)) |
224 | 224 |
225 assert len(streams) == 1 | 225 assert len(streams) == 1 |
226 return streams[0] | 226 return streams[0] |
227 | 227 |
228 def _match(self, stream, ctxt, match_templates=None): | 228 def _match(self, stream, ctxt, match_templates=None, **vars): |
229 """Internal stream filter that applies any defined match templates | 229 """Internal stream filter that applies any defined match templates |
230 to the stream. | 230 to the stream. |
231 """ | 231 """ |
232 if match_templates is None: | 232 if match_templates is None: |
233 match_templates = ctxt._match_templates | 233 match_templates = ctxt._match_templates |
269 for test in [mt[0] for mt in match_templates[idx + 1:]]: | 269 for test in [mt[0] for mt in match_templates[idx + 1:]]: |
270 test(event, namespaces, ctxt, updateonly=True) | 270 test(event, namespaces, ctxt, updateonly=True) |
271 | 271 |
272 # Consume and store all events until an end event | 272 # Consume and store all events until an end event |
273 # corresponding to this start event is encountered | 273 # corresponding to this start event is encountered |
274 inner = _strip(stream) | |
275 pre_match_templates = match_templates[:idx + 1] | 274 pre_match_templates = match_templates[:idx + 1] |
276 if 'match_once' not in hints and 'not_recursive' in hints: | 275 if 'match_once' not in hints and 'not_recursive' in hints: |
277 pre_match_templates.pop() | 276 pre_match_templates.pop() |
278 inner = self._match(inner, ctxt, pre_match_templates) | 277 inner = _strip(stream) |
279 content = list(self._include(chain([event], inner, tail), | 278 if pre_match_templates: |
280 ctxt)) | 279 inner = self._match(inner, ctxt, pre_match_templates) |
281 | 280 content = self._include(chain([event], inner, tail), ctxt) |
282 for test in [mt[0] for mt in match_templates]: | 281 if 'not_buffered' not in hints: |
283 test(tail[0], namespaces, ctxt, updateonly=True) | 282 content = list(content) |
283 | |
284 if tail: | |
285 for test in [mt[0] for mt in match_templates]: | |
286 test(tail[0], namespaces, ctxt, updateonly=True) | |
284 | 287 |
285 # Make the select() function available in the body of the | 288 # Make the select() function available in the body of the |
286 # match template | 289 # match template |
287 def select(path): | 290 def select(path): |
288 return Stream(content).select(path, namespaces, ctxt) | 291 return Stream(content).select(path, namespaces, ctxt) |
289 ctxt.push(dict(select=select)) | 292 vars = dict(select=select) |
290 | 293 |
291 # Recursively process the output | 294 # Recursively process the output |
292 template = _apply_directives(template, ctxt, directives) | 295 template = _apply_directives(template, directives, ctxt, |
293 remaining = match_templates | 296 **vars) |
294 for event in self._match(self._exec( | 297 for event in self._match( |
295 self._eval(self._flatten(template, ctxt), | 298 self._exec( |
296 ctxt), ctxt), ctxt, match_templates[idx + 1:]): | 299 self._eval( |
300 self._flatten(template, ctxt, **vars), | |
301 ctxt, **vars), | |
302 ctxt, **vars), | |
303 ctxt, match_templates[idx + 1:], **vars): | |
297 yield event | 304 yield event |
298 | 305 |
299 ctxt.pop() | |
300 break | 306 break |
301 | 307 |
302 else: # no matches | 308 else: # no matches |
303 yield event | 309 yield event |