summaryrefslogtreecommitdiffstats
path: root/docs/examples
diff options
context:
space:
mode:
Diffstat (limited to 'docs/examples')
-rw-r--r--docs/examples/cache_extension.py54
-rw-r--r--docs/examples/inline_gettext_extension.py72
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,
+ )