diff options
Diffstat (limited to 'docs/examples')
-rw-r--r-- | docs/examples/cache_extension.py | 54 | ||||
-rw-r--r-- | docs/examples/inline_gettext_extension.py | 72 |
2 files changed, 126 insertions, 0 deletions
diff --git a/docs/examples/cache_extension.py b/docs/examples/cache_extension.py new file mode 100644 index 0000000..46af67c --- /dev/null +++ b/docs/examples/cache_extension.py @@ -0,0 +1,54 @@ +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().__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 diff --git a/docs/examples/inline_gettext_extension.py b/docs/examples/inline_gettext_extension.py new file mode 100644 index 0000000..bf8b9db --- /dev/null +++ b/docs/examples/inline_gettext_extension.py @@ -0,0 +1,72 @@ +import re + +from jinja2.exceptions import TemplateSyntaxError +from jinja2.ext import Extension +from jinja2.lexer import count_newlines +from jinja2.lexer import Token + + +_outside_re = re.compile(r"\\?(gettext|_)\(") +_inside_re = re.compile(r"\\?[()]") + + +class InlineGettext(Extension): + """This extension implements support for inline gettext blocks:: + + <h1>_(Welcome)</h1> + <p>_(This is a paragraph)</p> + + Requires the i18n extension to be loaded and configured. + """ + + def filter_stream(self, stream): + paren_stack = 0 + + for token in stream: + if token.type != "data": + yield token + continue + + pos = 0 + lineno = token.lineno + + while True: + if not paren_stack: + match = _outside_re.search(token.value, pos) + else: + match = _inside_re.search(token.value, pos) + if match is None: + break + new_pos = match.start() + if new_pos > pos: + preval = token.value[pos:new_pos] + yield Token(lineno, "data", preval) + lineno += count_newlines(preval) + gtok = match.group() + if gtok[0] == "\\": + yield Token(lineno, "data", gtok[1:]) + elif not paren_stack: + yield Token(lineno, "block_begin", None) + yield Token(lineno, "name", "trans") + yield Token(lineno, "block_end", None) + paren_stack = 1 + else: + if gtok == "(" or paren_stack > 1: + yield Token(lineno, "data", gtok) + paren_stack += -1 if gtok == ")" else 1 + if not paren_stack: + yield Token(lineno, "block_begin", None) + yield Token(lineno, "name", "endtrans") + yield Token(lineno, "block_end", None) + pos = match.end() + + if pos < len(token.value): + yield Token(lineno, "data", token.value[pos:]) + + if paren_stack: + raise TemplateSyntaxError( + "unclosed gettext expression", + token.lineno, + stream.name, + stream.filename, + ) |