Edgewall Software

Ticket #584: checked-inlines-r584-v2.diff

File checked-inlines-r584-v2.diff, 6.4 KB (added by hodgestar, 10 years ago)

Checked inlining patch v2.

  • genshi/template/base.py

     
    452452    @property
    453453    def stream(self):
    454454        if not self._prepared:
    455             self._stream = list(self._prepare(self._stream))
    456             self._prepared = True
     455            self._prepare_self()
    457456        return self._stream
    458457
    459458    def _parse(self, source, encoding):
     
    470469        """
    471470        raise NotImplementedError
    472471
    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):
    474478        """Call the `attach` method of every directive found in the template.
    475479       
    476480        :param stream: the event stream of the template
    477481        """
    478482        from genshi.template.loader import TemplateNotFound
     483        if inlined is None:
     484            inlined = set((self.filepath,))
    479485
    480486        for kind, data, pos in stream:
    481487            if kind is SUB:
     
    486492                                                      namespaces, pos)
    487493                    if directive:
    488494                        directives.append(directive)
    489                 substream = self._prepare(substream)
     495                substream = self._prepare(substream, inlined)
    490496                if directives:
    491497                    yield kind, (directives, list(substream)), pos
    492498                else:
     
    495501            else:
    496502                if kind is INCLUDE:
    497503                    href, cls, fallback = data
    498                     if isinstance(href, basestring) and \
    499                             not getattr(self.loader, 'auto_reload', True):
     504                    tmpl_inlined = False
     505                    if (isinstance(href, basestring) and
     506                            not getattr(self.loader, 'auto_reload', True)):
    500507                        # If the path to the included template is static, and
    501508                        # 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
    503513                        try:
    504514                            tmpl = self.loader.load(href, relative_to=pos[0],
    505515                                                    cls=cls or self.__class__)
    506                             for event in tmpl.stream:
    507                                 yield event
    508516                        except TemplateNotFound:
    509517                            if fallback is None:
    510518                                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):
    512529                                yield event
     530                            tmpl_inlined = True
     531                    if tmpl_inlined:
    513532                        continue
    514                     elif fallback:
     533                    if fallback:
    515534                        # Otherwise the include is performed at run time
    516                         data = href, cls, list(self._prepare(fallback))
     535                        data = href, cls, list(
     536                            self._prepare(fallback, inlined))
     537                    yield kind, data, pos
     538                else:
     539                    yield kind, data, pos
    517540
    518                 yield kind, data, pos
    519 
    520541    def generate(self, *args, **kwargs):
    521542        """Apply the template to the given context data.
    522543       
  • genshi/template/markup.py

     
    284284
    285285            yield kind, data, pos
    286286
    287     def _prepare(self, stream):
    288         return Template._prepare(self,
    289             self._extract_includes(self._interpolate_attrs(stream))
    290         )
     287    def _prepare(self, stream, inlined=None):
     288        return Template._prepare(
     289            self, self._extract_includes(self._interpolate_attrs(stream)),
     290            inlined=inlined)
    291291
    292292    def add_directives(self, namespace, factory):
    293293        """Register a custom `DirectiveFactory` for a given namespace.
  • genshi/template/tests/markup.py

     
    580580        finally:
    581581            shutil.rmtree(dirname)
    582582
    583     def test_allow_exec_false(self):
     583    def test_include_inline_recursive(self):
     584        dirname = tempfile.mkdtemp(suffix='genshi_test')
     585        try:
     586            file1 = open(os.path.join(dirname, 'tmpl1.html'), 'w')
     587            try:
     588                file1.write(
     589                    '<div xmlns:xi="http://www.w3.org/2001/XInclude"'
     590                    '                xmlns:py="http://genshi.edgewall.org/">'
     591                    '$depth'
     592                    '<py:with vars="depth = depth + 1">'
     593                    '<xi:include href="tmpl1.html"'
     594                    '            py:if="depth &lt; 3"/>'
     595                    '</py:with>'
     596                    '</div>'
     597                )
     598            finally:
     599                file1.close()
     600
     601            loader = TemplateLoader([dirname], auto_reload=False)
     602            tmpl = loader.load('tmpl1.html')
     603            self.assertEqual(
     604                "<div>0<div>1<div>2</div></div></div>",
     605                tmpl.generate(depth=0).render(encoding=None))
     606        finally:
     607            shutil.rmtree(dirname)
     608
     609    def test_allow_exec_false(self):
    584610        xml = ("""<?python
    585611          title = "A Genshi Template"
    586612          ?>