def _template_mtime(self): mtimes = [] mtimes.append(os.path.getmtime(self.template.filename)) with codecs.open(self.template.filename, 'r', encoding="utf-8") as fp: text = fp.read() fp.close() ast = self.template_env.parse(text) refs = list(meta.find_referenced_templates(ast)) while len(refs) > 0: r = refs.pop() t = self.template_env.get_template(r) with codecs.open(t.filename, 'r', encoding="utf-8") as fp: text = fp.read() fp.close() mtimes.append(os.path.getmtime(t.filename)) ast = self.template_env.parse(text) refs.extend(list(meta.find_referenced_templates(ast))) return max(mtimes)
def test_find_refererenced_templates(self): ast = env.parse('{% extends "layout.html" %}{% include helper %}') i = meta.find_referenced_templates(ast) ast = env.parse( '{% extends "layout.html" %}{% from "test.html" import a, b as c %}{% import "meh.html" as meh %}{% include "muh.html" %}' ) i = meta.find_referenced_templates(ast)
def test_find_included_templates(self): ast = env.parse('{% include ["foo.html", "bar.html"] %}') i = meta.find_referenced_templates(ast) ast = env.parse('{% include ("foo.html", "bar.html") %}') i = meta.find_referenced_templates(ast) ast = env.parse('{% include ["foo.html", "bar.html", foo] %}') i = meta.find_referenced_templates(ast) ast = env.parse('{% include ("foo.html", "bar.html", foo) %}') i = meta.find_referenced_templates(ast)
def test_find_refererenced_templates(self): ast = env.parse('{% extends "layout.html" %}{% include helper %}') i = meta.find_referenced_templates(ast) assert i.next() == 'layout.html' assert i.next() is None assert list(i) == [] ast = env.parse('{% extends "layout.html" %}' '{% from "test.html" import a, b as c %}' '{% import "meh.html" as meh %}' '{% include "muh.html" %}') i = meta.find_referenced_templates(ast) assert list(i) == ['layout.html', 'test.html', 'meh.html', 'muh.html']
def test_find_refererenced_templates(self, env): ast = env.parse('{% extends "layout.html" %}{% include helper %}') i = meta.find_referenced_templates(ast) assert next(i) == 'layout.html' assert next(i) is None assert list(i) == [] ast = env.parse('{% extends "layout.html" %}' '{% from "test.html" import a, b as c %}' '{% import "meh.html" as meh %}' '{% include "muh.html" %}') i = meta.find_referenced_templates(ast) assert list(i) == ['layout.html', 'test.html', 'meh.html', 'muh.html']
def find_dependencies_recurse(file_path): new_deps = [] # Parse the file and extract the list of references with open(file_path, "r") as f: ast = env.parse(f.read().decode('utf-8')) # For each reference, find the absolute path. If no file # is found and the reference was not listed in exceptions, # throw an error. for reference in meta.find_referenced_templates(ast): reference_path = find_file_in_dirs(reference, templatedirs) if reference_path is None: if reference in exceptions: continue raise Exception("cannot find file '%s' referenced in " "'%s'" % (reference, file_path)) new_deps.append(reference_path) for dep in new_deps: # Make sure we don't have a circular reference if dep not in total_set: total_set.add(dep) find_dependencies_recurse(dep) return
def _get_last_modified(self, template_name, template_path=None): """Get the last modified time of the template. Use the inheritance chain to determine if anything in the chain is newer and should represent this template's last modified time. """ if template_name in self._templates_modified_times: return self._templates_modified_times[template_name] if template_path is None: template_path = os.path.join(self.templates_path, template_name) # Assume that the current modified time of the template is best. last_modified = os.path.getmtime(template_path) # Check for any parents and then check their modified times. with open(template_path, 'r') as f: source = f.read() ast = self._env.parse(source, template_name, template_path) templates = meta.find_referenced_templates(ast) for parent in templates: if parent is None: # Nothing helpful can be done with None, but it may show up. continue parent_last_modified = self._get_last_modified(parent) if parent_last_modified > last_modified: # The template should look at least as recent as its parent. last_modified = parent_last_modified self._templates_modified_times[template_name] = last_modified return last_modified
def test_find_included_templates(self): ast = env.parse('{% include ["foo.html", "bar.html"] %}') i = meta.find_referenced_templates(ast) assert list(i) == ['foo.html', 'bar.html'] ast = env.parse('{% include ("foo.html", "bar.html") %}') i = meta.find_referenced_templates(ast) assert list(i) == ['foo.html', 'bar.html'] ast = env.parse('{% include ["foo.html", "bar.html", foo] %}') i = meta.find_referenced_templates(ast) assert list(i) == ['foo.html', 'bar.html', None] ast = env.parse('{% include ("foo.html", "bar.html", foo) %}') i = meta.find_referenced_templates(ast) assert list(i) == ['foo.html', 'bar.html', None]
def imports(template, tpath=None): 'Return all files imported by template' path = os.path.dirname(os.path.realpath(template)) env = make_env(path) ast = env.parse(open(template, 'rb').read().decode()) subs = meta.find_referenced_templates(ast) return [os.path.join(path, one) for one in subs]
def test_find_included_templates(self, env): ast = env.parse('{% include ["foo.html", "bar.html"] %}') i = meta.find_referenced_templates(ast) assert list(i) == ['foo.html', 'bar.html'] ast = env.parse('{% include ("foo.html", "bar.html") %}') i = meta.find_referenced_templates(ast) assert list(i) == ['foo.html', 'bar.html'] ast = env.parse('{% include ["foo.html", "bar.html", foo] %}') i = meta.find_referenced_templates(ast) assert list(i) == ['foo.html', 'bar.html', None] ast = env.parse('{% include ("foo.html", "bar.html", foo) %}') i = meta.find_referenced_templates(ast) assert list(i) == ['foo.html', 'bar.html', None]
def resolve(parent): """We check whether any dependency (extend-block) has changed and update the bucket -- recursively. Returns True if the template itself or any parent template has changed. Otherwise False.""" if parent in self.resolved: return self.resolved[parent] source, filename, uptodate = self.get_source(environment, parent) bucket = bcc.get_bucket(environment, parent, filename, source) p = bcc._get_cache_filename(bucket) has_changed = getmtime(filename) > getmtime(p) if exists( p) else True if has_changed: # updating cached template if timestamp has changed code = environment.compile(source, parent, filename) bucket.code = code bcc.set_bucket(bucket) self.resolved[parent] = True return True ast = environment.parse(source) for name in meta.find_referenced_templates(ast): rv = resolve(name) if rv: # XXX double-return to break this recursion? return True
def resolve(parent): """We check whether any dependency (extend-block) has changed and update the bucket -- recursively. Returns True if the template itself or any parent template has changed. Otherwise False.""" if parent in self.resolved: return self.resolved[parent] source, filename, uptodate = self.get_source(environment, parent) bucket = bcc.get_bucket(environment, parent, filename, source) p = bcc._get_cache_filename(bucket) has_changed = getmtime(filename) > getmtime(p) if exists(p) else True if has_changed: # updating cached template if timestamp has changed code = environment.compile(source, parent, filename) bucket.code = code bcc.set_bucket(bucket) self.resolved[parent] = True return True ast = environment.parse(source) for name in meta.find_referenced_templates(ast): rv = resolve(name) if rv: # XXX double-return to break this recursion? return True
def validate(self, template_file): """ Find all available and overridden vars in a template. Recursively checks all super templates. :param template_file: The name of the template file :return: the set and unset variables :rtype: tuple """ # Get all the info for the CURRENT template # Get the source of the template template_source = self.env.loader.get_source(self.env, template_file)[0] # parse it into an abstract syntax tree ast = self.env.parse(template_source) # the UNSET variables in the current template unset_vars = meta.find_undeclared_variables(ast) # the SET variables in the current template set_vars = self.find_set_vars(ast) # validate the super templates super_templates = meta.find_referenced_templates(ast) for template in super_templates: # Get all the information about the super template recursively super_unset, super_set = self.validate(template) # We do it this way so values in derived templates override those in base templates super_set.update(set_vars) set_vars = super_set unset_vars = unset_vars.union(super_unset) return unset_vars, set_vars
def _get_last_modified(self, template_name, template_path=None): """Get the last modified time of the template. Use the inheritance chain to determine if anything in the chain is newer and should represent this template's last modified time. """ if template_name in self._templates_modified_times: return self._templates_modified_times[template_name] if template_path is None: template_path = os.path.join(self.templates_path, template_name) # Assume that the current modified time of the template is best. last_modified = os.path.getmtime(template_path) # Check for any parents and then check their modified times. with open(template_path, "r") as f: source = f.read() ast = self._env.parse(source, template_name, template_path) templates = meta.find_referenced_templates(ast) for parent in templates: if parent is None: # Nothing helpful can be done with None, but it may show up. continue parent_last_modified = self._get_last_modified(parent) if parent_last_modified > last_modified: # The template should look at least as recent as its parent. last_modified = parent_last_modified self._templates_modified_times[template_name] = last_modified return last_modified
def recurse(env, filename, includes): source = env.loader.get_source(env, filename)[0] parsed = env.parse(source) files = list(meta.find_referenced_templates(parsed)) for file in files: if file not in includes: includes.append(file) recurse(env, file, includes)
def _render_blocks(template_path): source = frappe.local.jloader.get_source(frappe.local.jenv, template_path)[0] for referenced_template_path in meta.find_referenced_templates(env.parse(source)): if referenced_template_path: _render_blocks(referenced_template_path) template = frappe.get_template(template_path) for block, render in template.blocks.items(): out[block] = scrub_relative_urls(concat(render(template.new_context(context))))
def get_template_vars(templatename, ignorevars=[], sort=True, maxnestlevels=100): """Return a list of all variables found in a Jinja template Arguments: ignorevars -- a list of variables that are removed from the output sort -- True (default) or False if returned list should be sorted maxnestlevels -- a positve integer which defines how deep you can nest templates with includes """ tplvars = [] templates = [] templatesseen = [] nestlevels = 0 #env = app.jinja_env env = create_jinja_env() templates.append(templatename) templatesseen.append(templatename) while len(templates) > 0: tpl = templates.pop() nested = False tplsrc = env.loader.get_source(env, tpl)[0] ast = env.parse(tplsrc) for template in meta.find_referenced_templates(ast): if template in templatesseen: raise Exception( "Template loop detected: \"{}\" references \"{}\" which was seen earlier" .format(tpl, template)) else: templates.append(template) templatesseen.append(template) nested = True for e in meta.find_undeclared_variables(ast): if not e in ignorevars: tplvars.append(e) if nested and nestlevels >= maxnestlevels: raise Exception( "Maximum template nesting depth of {} reached in template {}". format(maxnestlevels, template)) else: nestlevels += 1 if sort: return sorted(tplvars) else: return tplvars
def render(source_files, output_dir, context=None): """Render user provided source files into a QIIME 2 visualization template. Parameters ---------- source_files : str, or list of str Files to be rendered and written to the output_dir. output_dir : str The output_dir provided to a visualiation function by the QIIME 2 framework. context : dict, optional The context dictionary to be rendered into the source_files. The same context will be provided to all templates being rendered. """ src = get_iterable(source_files) # TODO: Hook into qiime.sdk.config.TemporaryDirectory() when it exists temp_dir = tempfile.TemporaryDirectory() template_data = pkg_resources.resource_filename('q2templates', 'templates') env = Environment(loader=FileSystemLoader(temp_dir.name), auto_reload=True) shutil.copy2(os.path.join(template_data, 'base.html'), temp_dir.name) for source_file in src: with open(source_file, 'r') as fh: ast = env.parse(fh.read()) for template in list(meta.find_referenced_templates(ast)): if template not in os.listdir(temp_dir.name): shutil.copy2(os.path.join(template_data, template), temp_dir.name) if context is None: context = {} # Grab the plugin and visualizer method name for default titles stack = inspect.stack() caller_frame = stack[1] caller_filename = caller_frame[0] caller_module = inspect.getmodule(caller_filename) plugin = caller_module.__name__.split('.')[0] method = caller_frame[3] context['q2templates_default_page_title'] = '%s : %s' % (plugin, method) # Copy user files to the environment for rendering to the output_dir for source_file in src: shutil.copy2(source_file, temp_dir.name) filename = os.path.basename(source_file) template = env.get_template(filename) rendered_content = template.render(**context) with open(os.path.join(output_dir, filename), "w") as fh: fh.write(rendered_content) # Move the style assets to the output_dir template_assets = os.path.join(template_data, 'assets') output_assets = os.path.join(output_dir, 'q2templateassets') copy_assets(template_assets, output_assets)
def find_jinja_deps(self, filename): """Return all (maybe partial) templates extended, imported or included by filename. """ # TODO Check whether this function is called only at one place (hence # could be integrated) source = self._env.loader.get_source(self._env, filename)[0] ast = self._env.parse(source) return find_referenced_templates(ast)
def _recursing_template_search(self, template_name): template_source = self.env.loader.get_source(self.env, template_name)[0] parsed_content = self.env.parse(template_source) deps = [] for item in Jinja2Meta.find_referenced_templates(parsed_content): deps.append(item) deps += self._recursing_template_search(item) return deps
def _getVariables(self, text, var_set): ast = self._jinja_env.parse(text) var_set.update(meta.find_undeclared_variables(ast)) for tpl_fname in meta.find_referenced_templates(ast): fname = os.path.join(self._dirname, tpl_fname) try: text = readTextFile(fname) self._getVariables(text, var_set) except EnvironmentError: pass
def get_string_deps(self, text): """Find dependencies for a template string.""" deps = set([]) ast = self.lookup.parse(text) dep_names = meta.find_referenced_templates(ast) for dep_name in dep_names: filename = self.lookup.loader.get_source(self.lookup, dep_name)[1] sub_deps = [filename] + self.get_deps(filename) self.dependency_cache[dep_name] = sub_deps deps |= set(sub_deps) return list(deps)
def get_string_deps(self, text): """Find dependencies for a template string.""" deps = set([]) ast = self.lookup.parse(text) dep_names = [d for d in meta.find_referenced_templates(ast) if d] for dep_name in dep_names: filename = self.lookup.loader.get_source(self.lookup, dep_name)[1] sub_deps = [filename] + self.get_deps(filename) self.dependency_cache[dep_name] = sub_deps deps |= set(sub_deps) return list(deps)
def render_blocks(template_path, out, context): """Build the template block by block from the main template.""" env = frappe.get_jenv() source = frappe.local.jloader.get_source(frappe.local.jenv, template_path)[0] for referenced_template_path in meta.find_referenced_templates(env.parse(source)): if referenced_template_path: render_blocks(referenced_template_path, out, context) template = frappe.get_template(template_path) for block, render in template.blocks.items(): new_context = template.new_context(context) out[block] = concat(render(new_context))
def _find_referenced_templates(self, name, source, environment): try: ast = environment.parse(source) except: # NOQA: E722 print("Error rendering template " + name) raise references = [x for x in meta.find_referenced_templates(ast)] for name in references: with open(join(self.path, name), "rb") as f: source = f.read().decode("utf-8") references.extend( self._find_referenced_templates(name, source, environment)) return references
def get_variables(self, filename): variables = [] env = Environment(loader=FileSystemLoader(searchpath=self._ngsi_ld)) template_source = env.loader.get_source(env, filename)[0] parsed_content = env.parse(template_source) templates = list(meta.find_referenced_templates(parsed_content)) if len(templates) > 0: for template in templates: for variable in self.get_variables(template): variables.append(variable) for variable in meta.find_undeclared_variables(parsed_content): variables.append(variable) return variables
def imports(template, tpath=None): 'Return all files imported by template' #print(f'jinja imports for {template} with {tpath}') path = search_path(template, tpath) style_params = get_style(template) env = make_env(path, **style_params) ast = env.parse(open(template, 'rb').read().decode()) subs = meta.find_referenced_templates(ast) # Note: this probably violates Jinja API as the env does not # expose the loader and certainly not its type. But, we make the # loader so let's use it to make sure it knows how to find imports # correctly. If this breaks, then we instead may pass tpath to # moo's resolve(). return [env.loader.get_source(env, s)[1] for s in subs]
def load(self, environment, name, globals=None): bcc = environment.bytecode_cache if globals is None: globals = {} deps = [ name, ] while len(deps) > 0: child = deps.pop() if child in self.modified: continue source, filename, uptodate = self.get_source(environment, child) bucket = bcc.get_bucket(environment, child, filename, source) try: modified = getmtime(filename) > getmtime( bcc._get_cache_filename(bucket)) except OSError: modified = True self.modified[child] = modified if modified: # updating cached template if timestamp has changed code = environment.compile(source, child, filename) bucket.code = code bcc.set_bucket(bucket) ast = environment.parse(source) for parent in meta.find_referenced_templates(ast): self.resolved[child].add(parent) deps.append(parent) for args, kwargs in find_assets(ast): self.assets[name].append((args, kwargs)) source, filename, uptodate = self.get_source(environment, name) code = bcc.get_bucket(environment, name, filename, source).code if code is None: code = environment.compile(source, name, filename) tt = environment.template_class.from_code(environment, code, globals, uptodate) return tt
def _render_blocks(template_path): #print "template_paths {}".format(template_path) source = frappe.local.floader.get_source(frappe.local.fenv, template_path)[0] for referenced_template_path in meta.find_referenced_templates( env.parse(source)): if referenced_template_path: _render_blocks(referenced_template_path) template = fluorine_get_template(template_path) for block, render in template.blocks.items(): make_heritage(block, context) out[block] = scrub_relative_urls( concat(render(template.new_context(context))))
def get_template_vars(self, ignorevars=[], sort=True, maxnestlevels=100): """Return a list of all variables found in the template Arguments: ignorevars -- a list of variables that are removed from the output sort -- True (default) or False if returned list should be sorted maxnestlevels -- a positve integer which defines how deep you can nest templates with includes """ tplvars = [] templates = [] templatesseen = [] nestlevels = 0 env = Environment(loader=FileSystemLoader(self.templatepath), undefined=StrictUndefined) templates.append(self.templatename) templatesseen.append(self.templatename) while len(templates) > 0: tpl = templates.pop() nested = False tplsrc = env.loader.get_source(env, tpl)[0] ast = env.parse(tplsrc) for template in meta.find_referenced_templates(ast): if template in templatesseen: raise Exception("Template loop detected: \"{}\" references \"{}\" which was seen earlier".format(tpl, template)) else: templates.append(template) templatesseen.append(template) nested = True for e in meta.find_undeclared_variables(ast): if not e in ignorevars and not e in tplvars: tplvars.append(e) if nested and nestlevels >= maxnestlevels: raise Exception("Maximum template nesting depth of {} reached in template {}".format(maxnestlevels, template)) else: nestlevels += 1 if sort: return sorted(tplvars) else: return tplvars
def get_dependencies(self, path): """ Finds dependencies hierarchically based on the included files. """ text = self.env.loader.get_source(self.env, path)[0] from jinja2.meta import find_referenced_templates ast = self.env.parse(text) tpls = find_referenced_templates(ast) deps = list(self.env.globals['deps'].get('path', [])) for dep in tpls: deps.append(dep) if dep: deps.extend(self.get_dependencies(dep)) return list(set(deps))
def get_referenced_templates(self, template): """ Request the template's Abstract Syntax Tree so we can find other template references. Store the reference list in a dictionary """ if not template in self.template_trees: try: ast = self.env.parse(self.env.loader.get_source(self.env, template)) self.template_trees[template] = list(meta.find_referenced_templates(ast)) except: self.template_trees[template] = list() self.reporter.verbose("\033[34m%s\033[0m references templates \033[32m%s\033[0m" % (template, self.template_trees[template])) return self.template_trees[template]
def load(self, environment, name, globals=None): bcc = environment.bytecode_cache if globals is None: globals = {} deps = [name, ] while len(deps) > 0: child = deps.pop() if child in self.modified: continue source, filename, uptodate = self.get_source(environment, child) bucket = bcc.get_bucket(environment, child, filename, source) try: modified = getmtime(filename) > getmtime(bcc._get_cache_filename(bucket)) except OSError: modified = True self.modified[child] = modified if modified: # updating cached template if timestamp has changed code = environment.compile(source, child, filename) bucket.code = code bcc.set_bucket(bucket) ast = environment.parse(source) for parent in meta.find_referenced_templates(ast): self.resolved[child].add(parent) deps.append(parent) for args, kwargs in find_assets(ast): self.assets[name].append((args, kwargs)) source, filename, uptodate = self.get_source(environment, name) code = bcc.get_bucket(environment, name, filename, source).code if code is None: code = environment.compile(source, name, filename) tt = environment.template_class.from_code(environment, code, globals, uptodate) return tt
def _iter_template_content(self, templatename, *, skip=None): """Iterate over template (and subtemplate) content.""" if skip is None: skip = [] template = self.jinjaenv.get_template(templatename) with patacrep.encoding.open_read( template.filename, encoding=self.encoding ) as contentfile: content = contentfile.read() for subtemplatename in find_referenced_templates(self.jinjaenv.parse(content)): if subtemplatename not in skip: yield from self._iter_template_content( subtemplatename, skip=skip + [templatename], ) yield template.name, content
def find_referenced_templates(template, search_path): """ Returns a list of files which can be either {% imported %}, {% extended %} or {% included %} within a template. """ from jinja2 import Environment, meta env = Environment() ast = env.parse(template.read()) referenced_templates = list(meta.find_referenced_templates(ast)) def realpath(tpl): for path in search_path: t = os.path.realpath(os.path.join(path, tpl)) if os.path.isfile(t): return t return None return [realpath(t) for t in referenced_templates if t is not None]
def choose_template_from_url(self, url): env = Environment() ast = env.parse('{% include "dist/styles/guitartuner-core.css" %}') print list(meta.find_referenced_templates(ast)) print os.path.dirname(__file__) deeplink_class = '' if (url != '/'): deeplink_class = 'app-deeplink' return { 'path': 'dist/index.html', 'data': { 'deeplink_class': deeplink_class } }
def get_string_deps(self, text, context=None): """Find dependencies for a template string.""" deps = set([]) ast = self.lookup.parse(text) simple_dep_names = [ d for d in meta.find_referenced_templates(ast) if d ] formatted_dep_names = [ imp.template.left.value % (context[imp.template.right.name], ) for imp in ast.find_all(jinja2.nodes.Import) if isinstance(imp.template, jinja2.nodes.Mod) ] dep_names = simple_dep_names + formatted_dep_names for dep_name in dep_names: filename = self.lookup.loader.get_source(self.lookup, dep_name)[1] sub_deps = [filename] + self.get_deps(filename, context) self.dependency_cache[dep_name] = sub_deps deps |= set(sub_deps) return list(deps)
def get_dependencies(self, path): """ Finds dependencies hierarchically based on the included files. """ text = self.env.loader.get_source(self.env, path)[0] from jinja2.meta import find_referenced_templates try: ast = self.env.parse(text) except: logger.error("Error parsing[%s]" % path) raise tpls = find_referenced_templates(ast) deps = list(self.env.globals["deps"].get("path", [])) for dep in tpls: deps.append(dep) if dep: deps.extend(self.get_dependencies(dep)) return list(set(deps))
def get_dependencies(self, path): """ Finds dependencies hierarchically based on the included files. """ text = self.env.loader.get_source(self.env, path)[0] from jinja2.meta import find_referenced_templates try: ast = self.env.parse(text) except Exception as e: HydeException.reraise("Error processing %s: \n%s" % (path, str(e)), sys.exc_info()) tpls = find_referenced_templates(ast) deps = list(self.env.globals['deps'].get('path', [])) for dep in tpls: deps.append(dep) if dep: deps.extend(self.get_dependencies(dep)) return list(set(deps))
def get_dependencies(self, path): """ Finds dependencies hierarchically based on the included files. """ text = self.env.loader.get_source(self.env, path)[0] from jinja2.meta import find_referenced_templates try: ast = self.env.parse(text) except Exception as e: HydeException.reraise("Error processing %s: \n%s" % (path, str(e)), sys.exc_info()) tpls = find_referenced_templates(ast) deps = list(self.env.globals["deps"].get("path", [])) for dep in tpls: deps.append(dep) if dep: deps.extend(self.get_dependencies(dep)) return list(set(deps))
def template_deps(self, template_name): # Cache the lists of dependencies for each template name. if self.dependency_cache.get(template_name) is None: # Use a breadth-first search to find all templates this one # depends on. queue = deque([template_name]) visited_templates = set([template_name]) deps = [] while len(queue) > 0: curr = queue.popleft() source, filename = self.lookup.loader.get_source(self.lookup, curr)[:2] deps.append(filename) ast = self.lookup.parse(source) dep_names = meta.find_referenced_templates(ast) for dep_name in dep_names: if dep_name not in visited_templates and dep_name is not None: visited_templates.add(dep_name) queue.append(dep_name) self.dependency_cache[template_name] = deps return self.dependency_cache[template_name]
def get_referenced_templates(self, template): """ Request the template's Abstract Syntax Tree so we can find other template references. Store the reference list in a dictionary """ if not template in self.template_trees: try: ast = self.env.parse( self.env.loader.get_source(self.env, template)) self.template_trees[template] = list( meta.find_referenced_templates(ast)) except: self.template_trees[template] = list() self.reporter.verbose( "\033[34m%s\033[0m references templates \033[32m%s\033[0m" % (template, self.template_trees[template])) return self.template_trees[template]
def _recurse_template_search(self, env, template_name): """ Load involved template sources from given template file path then find their template references. Arguments: env (jinja2.Jinja2Environment): Jinja environment. template_name (string): Template file path. Returns: list: List of involved templates sources files. """ template_source = env.loader.get_source(env, template_name)[0] parsed_content = env.parse(template_source) deps = [] for item in Jinja2Meta.find_referenced_templates(parsed_content): deps.append(item) deps += self._recurse_template_search(env, item) return deps
def _get_requirements(self, template_name): try: return list(meta.find_referenced_templates(self.env.parse(self.loader.get_source(self.env, template_name)))) except Exception as e: logger.error("Error analyzing {0}".format(template_name), exc_info=True) return []
def test_find_refererenced_templates(self): ast = env.parse('{% extends "layout.html" %}{% include helper %}') i = meta.find_referenced_templates(ast) ast = env.parse('{% extends "layout.html" %}{% from "test.html" import a, b as c %}{% import "meh.html" as meh %}{% include "muh.html" %}') i = meta.find_referenced_templates(ast)
def get_template_files(template_env, tmpl_name): """Get the full list of files parsed to process this template""" raw_src = template_env.loader.get_source(template_env, tmpl_name)[0] ast = template_env.parse(raw_src) included = meta.find_referenced_templates(ast) return list(included) + [tmpl_name]
def _read(self, relpath): ast = self.env.parse(self.loader(relpath)) deps = set(jinmeta.find_referenced_templates(ast)) return deps
#!/usr/bin/env python import jinja2 import sys from jinja2 import meta if len(sys.argv) != 2: print "Usage:", sys.argv[0], "filename" sys.exit(-1) page = sys.argv[1] env = jinja2.Environment(loader=jinja2.FileSystemLoader(["templates", "pages"])) with open(page, "r") as p: ast = env.parse("".join(p.readlines())) dependencies = filter(lambda x: x != None, list(meta.find_referenced_templates(ast))) if len(dependencies) > 0: dependencies = ["templates/" + x for x in dependencies] print page.replace("pages/", "site/") + ":", " ".join(dependencies)