text: from jinja2 import nodes
  from jinja2.ext import Extension
  
  
  class FragmentCacheExtension(Extension):
      # a set of names that trigger the extension.
      tags = {'cache'}
  
      def __init__(self, environment):
          super(FragmentCacheExtension, self).__init__(environment)
  
          # add the defaults to the environment
          environment.extend(
              fragment_cache_prefix='',
              fragment_cache=None
          )
  
      def parse(self, parser):
          # the first token is the token that started the tag.  In our case
          # we only listen to ``'cache'`` so this will be a name token with
          # `cache` as value.  We get the line number so that we can give
          # that line number to the nodes we create by hand.
          lineno = next(parser.stream).lineno
  
          # now we parse a single expression that is used as cache key.
          args = [parser.parse_expression()]
  
          # if there is a comma, the user provided a timeout.  If not use
          # None as second parameter.
          if parser.stream.skip_if('comma'):
              args.append(parser.parse_expression())
          else:
              args.append(nodes.Const(None))
  
          # now we parse the body of the cache block up to `endcache` and
          # drop the needle (which would always be `endcache` in that case)
          body = parser.parse_statements(['name:endcache'], drop_needle=True)
  
          # now return a `CallBlock` node that calls our _cache_support
          # helper method on this extension.
          return nodes.CallBlock(self.call_method('_cache_support', args),
                                 [], [], body).set_lineno(lineno)
  
      def _cache_support(self, name, timeout, caller):
          """Helper callback."""
          key = self.environment.fragment_cache_prefix + name
  
          # try to load the block from the cache
          # if there is no fragment in the cache, render it and store
          # it in the cache.
          rv = self.environment.fragment_cache.get(key)
          if rv is not None:
              return rv
          rv = caller()
          self.environment.fragment_cache.add(key, rv, timeout)
          return rv
  