Index: third_party/jinja2/meta.py |
diff --git a/third_party/jinja2/meta.py b/third_party/jinja2/meta.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3a779a5e9a81a6b59b0fa1685c63e62e38a70b9c |
--- /dev/null |
+++ b/third_party/jinja2/meta.py |
@@ -0,0 +1,102 @@ |
+# -*- coding: utf-8 -*- |
+""" |
+ jinja2.meta |
+ ~~~~~~~~~~~ |
+ |
+ This module implements various functions that exposes information about |
+ templates that might be interesting for various kinds of applications. |
+ |
+ :copyright: (c) 2010 by the Jinja Team, see AUTHORS for more details. |
+ :license: BSD, see LICENSE for more details. |
+""" |
+from jinja2 import nodes |
+from jinja2.compiler import CodeGenerator |
+ |
+ |
+class TrackingCodeGenerator(CodeGenerator): |
+ """We abuse the code generator for introspection.""" |
+ |
+ def __init__(self, environment): |
+ CodeGenerator.__init__(self, environment, '<introspection>', |
+ '<introspection>') |
+ self.undeclared_identifiers = set() |
+ |
+ def write(self, x): |
+ """Don't write.""" |
+ |
+ def pull_locals(self, frame): |
+ """Remember all undeclared identifiers.""" |
+ self.undeclared_identifiers.update(frame.identifiers.undeclared) |
+ |
+ |
+def find_undeclared_variables(ast): |
+ """Returns a set of all variables in the AST that will be looked up from |
+ the context at runtime. Because at compile time it's not known which |
+ variables will be used depending on the path the execution takes at |
+ runtime, all variables are returned. |
+ |
+ >>> from jinja2 import Environment, meta |
+ >>> env = Environment() |
+ >>> ast = env.parse('{% set foo = 42 %}{{ bar + foo }}') |
+ >>> meta.find_undeclared_variables(ast) |
+ set(['bar']) |
+ |
+ .. admonition:: Implementation |
+ |
+ Internally the code generator is used for finding undeclared variables. |
+ This is good to know because the code generator might raise a |
+ :exc:`TemplateAssertionError` during compilation and as a matter of |
+ fact this function can currently raise that exception as well. |
+ """ |
+ codegen = TrackingCodeGenerator(ast.environment) |
+ codegen.visit(ast) |
+ return codegen.undeclared_identifiers |
+ |
+ |
+def find_referenced_templates(ast): |
+ """Finds all the referenced templates from the AST. This will return an |
+ iterator over all the hardcoded template extensions, inclusions and |
+ imports. If dynamic inheritance or inclusion is used, `None` will be |
+ yielded. |
+ |
+ >>> from jinja2 import Environment, meta |
+ >>> env = Environment() |
+ >>> ast = env.parse('{% extends "layout.html" %}{% include helper %}') |
+ >>> list(meta.find_referenced_templates(ast)) |
+ ['layout.html', None] |
+ |
+ This function is useful for dependency tracking. For example if you want |
+ to rebuild parts of the website after a layout template has changed. |
+ """ |
+ for node in ast.find_all((nodes.Extends, nodes.FromImport, nodes.Import, |
+ nodes.Include)): |
+ if not isinstance(node.template, nodes.Const): |
+ # a tuple with some non consts in there |
+ if isinstance(node.template, (nodes.Tuple, nodes.List)): |
+ for template_name in node.template.items: |
+ # something const, only yield the strings and ignore |
+ # non-string consts that really just make no sense |
+ if isinstance(template_name, nodes.Const): |
+ if isinstance(template_name.value, basestring): |
+ yield template_name.value |
+ # something dynamic in there |
+ else: |
+ yield None |
+ # something dynamic we don't know about here |
+ else: |
+ yield None |
+ continue |
+ # constant is a basestring, direct template name |
+ if isinstance(node.template.value, basestring): |
+ yield node.template.value |
+ # a tuple or list (latter *should* not happen) made of consts, |
+ # yield the consts that are strings. We could warn here for |
+ # non string values |
+ elif isinstance(node, nodes.Include) and \ |
+ isinstance(node.template.value, (tuple, list)): |
+ for template_name in node.template.value: |
+ if isinstance(template_name, basestring): |
+ yield template_name |
+ # something else we don't care about, we could warn here |
+ else: |
+ yield None |