# -*- coding: utf-8 -*-"""Functions that expose information about templates that might beinteresting for introspection."""from . import nodesfrom ._compat import iteritemsfrom ._compat import string_typesfrom .compiler import CodeGeneratorclass 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 enter_frame(self, frame):"""Remember all undeclared identifiers."""CodeGenerator.enter_frame(self, frame)for _, (action, param) in iteritems(frame.symbols.loads):if action == "resolve" and param not in self.environment.globals:self.undeclared_identifiers.add(param)def find_undeclared_variables(ast):"""Returns a set of all variables in the AST that will be looked up fromthe context at runtime. Because at compile time it's not known whichvariables will be used depending on the path the execution takes atruntime, 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'])True.. admonition:: ImplementationInternally 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 offact this function can currently raise that exception as well."""codegen = TrackingCodeGenerator(ast.environment)codegen.visit(ast)return codegen.undeclared_identifiersdef find_referenced_templates(ast):"""Finds all the referenced templates from the AST. This will return aniterator over all the hardcoded template extensions, inclusions andimports. If dynamic inheritance or inclusion is used, `None` will beyielded.>>> 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 wantto 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 thereif 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 senseif isinstance(template_name, nodes.Const):if isinstance(template_name.value, string_types):yield template_name.value# something dynamic in thereelse:yield None# something dynamic we don't know about hereelse:yield Nonecontinue# constant is a basestring, direct template nameif isinstance(node.template.value, string_types):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 valueselif isinstance(node, nodes.Include) and isinstance(node.template.value, (tuple, list)):for template_name in node.template.value:if isinstance(template_name, string_types):yield template_name# something else we don't care about, we could warn hereelse:yield None
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。