comparison genshi/template/base.py @ 1032:56fd1ca051af stable-0.7.x

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