Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/jinja2/meta.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:32:28 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:d30785e31577 | 1:56ad4e20f292 |
|---|---|
| 1 # -*- coding: utf-8 -*- | |
| 2 """Functions that expose information about templates that might be | |
| 3 interesting for introspection. | |
| 4 """ | |
| 5 from . import nodes | |
| 6 from ._compat import iteritems | |
| 7 from ._compat import string_types | |
| 8 from .compiler import CodeGenerator | |
| 9 | |
| 10 | |
| 11 class TrackingCodeGenerator(CodeGenerator): | |
| 12 """We abuse the code generator for introspection.""" | |
| 13 | |
| 14 def __init__(self, environment): | |
| 15 CodeGenerator.__init__(self, environment, "<introspection>", "<introspection>") | |
| 16 self.undeclared_identifiers = set() | |
| 17 | |
| 18 def write(self, x): | |
| 19 """Don't write.""" | |
| 20 | |
| 21 def enter_frame(self, frame): | |
| 22 """Remember all undeclared identifiers.""" | |
| 23 CodeGenerator.enter_frame(self, frame) | |
| 24 for _, (action, param) in iteritems(frame.symbols.loads): | |
| 25 if action == "resolve" and param not in self.environment.globals: | |
| 26 self.undeclared_identifiers.add(param) | |
| 27 | |
| 28 | |
| 29 def find_undeclared_variables(ast): | |
| 30 """Returns a set of all variables in the AST that will be looked up from | |
| 31 the context at runtime. Because at compile time it's not known which | |
| 32 variables will be used depending on the path the execution takes at | |
| 33 runtime, all variables are returned. | |
| 34 | |
| 35 >>> from jinja2 import Environment, meta | |
| 36 >>> env = Environment() | |
| 37 >>> ast = env.parse('{% set foo = 42 %}{{ bar + foo }}') | |
| 38 >>> meta.find_undeclared_variables(ast) == set(['bar']) | |
| 39 True | |
| 40 | |
| 41 .. admonition:: Implementation | |
| 42 | |
| 43 Internally the code generator is used for finding undeclared variables. | |
| 44 This is good to know because the code generator might raise a | |
| 45 :exc:`TemplateAssertionError` during compilation and as a matter of | |
| 46 fact this function can currently raise that exception as well. | |
| 47 """ | |
| 48 codegen = TrackingCodeGenerator(ast.environment) | |
| 49 codegen.visit(ast) | |
| 50 return codegen.undeclared_identifiers | |
| 51 | |
| 52 | |
| 53 def find_referenced_templates(ast): | |
| 54 """Finds all the referenced templates from the AST. This will return an | |
| 55 iterator over all the hardcoded template extensions, inclusions and | |
| 56 imports. If dynamic inheritance or inclusion is used, `None` will be | |
| 57 yielded. | |
| 58 | |
| 59 >>> from jinja2 import Environment, meta | |
| 60 >>> env = Environment() | |
| 61 >>> ast = env.parse('{% extends "layout.html" %}{% include helper %}') | |
| 62 >>> list(meta.find_referenced_templates(ast)) | |
| 63 ['layout.html', None] | |
| 64 | |
| 65 This function is useful for dependency tracking. For example if you want | |
| 66 to rebuild parts of the website after a layout template has changed. | |
| 67 """ | |
| 68 for node in ast.find_all( | |
| 69 (nodes.Extends, nodes.FromImport, nodes.Import, nodes.Include) | |
| 70 ): | |
| 71 if not isinstance(node.template, nodes.Const): | |
| 72 # a tuple with some non consts in there | |
| 73 if isinstance(node.template, (nodes.Tuple, nodes.List)): | |
| 74 for template_name in node.template.items: | |
| 75 # something const, only yield the strings and ignore | |
| 76 # non-string consts that really just make no sense | |
| 77 if isinstance(template_name, nodes.Const): | |
| 78 if isinstance(template_name.value, string_types): | |
| 79 yield template_name.value | |
| 80 # something dynamic in there | |
| 81 else: | |
| 82 yield None | |
| 83 # something dynamic we don't know about here | |
| 84 else: | |
| 85 yield None | |
| 86 continue | |
| 87 # constant is a basestring, direct template name | |
| 88 if isinstance(node.template.value, string_types): | |
| 89 yield node.template.value | |
| 90 # a tuple or list (latter *should* not happen) made of consts, | |
| 91 # yield the consts that are strings. We could warn here for | |
| 92 # non string values | |
| 93 elif isinstance(node, nodes.Include) and isinstance( | |
| 94 node.template.value, (tuple, list) | |
| 95 ): | |
| 96 for template_name in node.template.value: | |
| 97 if isinstance(template_name, string_types): | |
| 98 yield template_name | |
| 99 # something else we don't care about, we could warn here | |
| 100 else: | |
| 101 yield None |
