comparison genshi/template/base.py @ 1033:348ba73df25c stable-0.6.x

Merge r1257 from trunk (fix for infinite template inlining).
author hodgestar
date Wed, 19 Mar 2014 13:56:46 +0000
parents cccbcbd33e90
children
comparison
equal deleted inserted replaced
1018:fa0e84724fee 1033:348ba73df25c
449 self.loader = TemplateLoader([os.path.abspath(basedir)]) 449 self.loader = TemplateLoader([os.path.abspath(basedir)])
450 450
451 @property 451 @property
452 def stream(self): 452 def stream(self):
453 if not self._prepared: 453 if not self._prepared:
454 self._stream = list(self._prepare(self._stream)) 454 self._prepare_self()
455 self._prepared = True
456 return self._stream 455 return self._stream
457 456
458 def _parse(self, source, encoding): 457 def _parse(self, source, encoding):
459 """Parse the template. 458 """Parse the template.
460 459
467 template, or an XML event stream 466 template, or an XML event stream
468 :param encoding: the encoding of the `source` 467 :param encoding: the encoding of the `source`
469 """ 468 """
470 raise NotImplementedError 469 raise NotImplementedError
471 470
472 def _prepare(self, stream): 471 def _prepare_self(self, inlined=None):
472 if not self._prepared:
473 self._stream = list(self._prepare(self._stream, inlined))
474 self._prepared = True
475
476 def _prepare(self, stream, inlined):
473 """Call the `attach` method of every directive found in the template. 477 """Call the `attach` method of every directive found in the template.
474 478
475 :param stream: the event stream of the template 479 :param stream: the event stream of the template
476 """ 480 """
477 from genshi.template.loader import TemplateNotFound 481 from genshi.template.loader import TemplateNotFound
482 if inlined is None:
483 inlined = set((self.filepath,))
478 484
479 for kind, data, pos in stream: 485 for kind, data, pos in stream:
480 if kind is SUB: 486 if kind is SUB:
481 directives = [] 487 directives = []
482 substream = data[1] 488 substream = data[1]
483 for _, cls, value, namespaces, pos in sorted(data[0]): 489 for _, cls, value, namespaces, pos in sorted(data[0]):
484 directive, substream = cls.attach(self, substream, value, 490 directive, substream = cls.attach(self, substream, value,
485 namespaces, pos) 491 namespaces, pos)
486 if directive: 492 if directive:
487 directives.append(directive) 493 directives.append(directive)
488 substream = self._prepare(substream) 494 substream = self._prepare(substream, inlined)
489 if directives: 495 if directives:
490 yield kind, (directives, list(substream)), pos 496 yield kind, (directives, list(substream)), pos
491 else: 497 else:
492 for event in substream: 498 for event in substream:
493 yield event 499 yield event
494 else: 500 else:
495 if kind is INCLUDE: 501 if kind is INCLUDE:
496 href, cls, fallback = data 502 href, cls, fallback = data
497 if isinstance(href, basestring) and \ 503 tmpl_inlined = False
498 not getattr(self.loader, 'auto_reload', True): 504 if (isinstance(href, basestring) and
505 not getattr(self.loader, 'auto_reload', True)):
499 # If the path to the included template is static, and 506 # If the path to the included template is static, and
500 # auto-reloading is disabled on the template loader, 507 # auto-reloading is disabled on the template loader,
501 # the template is inlined into the stream 508 # the template is inlined into the stream provided it
509 # is not already in the stack of templates being
510 # processed.
511 tmpl = None
502 try: 512 try:
503 tmpl = self.loader.load(href, relative_to=pos[0], 513 tmpl = self.loader.load(href, relative_to=pos[0],
504 cls=cls or self.__class__) 514 cls=cls or self.__class__)
505 for event in tmpl.stream:
506 yield event
507 except TemplateNotFound: 515 except TemplateNotFound:
508 if fallback is None: 516 if fallback is None:
509 raise 517 raise
510 for event in self._prepare(fallback): 518 if tmpl is not None:
519 if tmpl.filepath not in inlined:
520 inlined.add(tmpl.filepath)
521 tmpl._prepare_self(inlined)
522 for event in tmpl.stream:
523 yield event
524 inlined.discard(tmpl.filepath)
525 tmpl_inlined = True
526 else:
527 for event in self._prepare(fallback, inlined):
511 yield event 528 yield event
529 tmpl_inlined = True
530 if tmpl_inlined:
512 continue 531 continue
513 elif fallback: 532 if fallback:
514 # Otherwise the include is performed at run time 533 # Otherwise the include is performed at run time
515 data = href, cls, list(self._prepare(fallback)) 534 data = href, cls, list(
516 535 self._prepare(fallback, inlined))
517 yield kind, data, pos 536 yield kind, data, pos
537 else:
538 yield kind, data, pos
518 539
519 def generate(self, *args, **kwargs): 540 def generate(self, *args, **kwargs):
520 """Apply the template to the given context data. 541 """Apply the template to the given context data.
521 542
522 Any keyword arguments are made available to the template as context 543 Any keyword arguments are made available to the template as context
Copyright (C) 2012-2017 Edgewall Software