Skip to content

Instantly share code, notes, and snippets.

@Zoramite
Last active July 22, 2019 01:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zoramite/f4c42620d7b564a26a398d8d25ecb419 to your computer and use it in GitHub Desktop.
Save Zoramite/f4c42620d7b564a26a398d8d25ecb419 to your computer and use it in GitHub Desktop.
Jinja2 Dependency Detection
"""Test how the Jinja templates"""
import os
import jinja2
from jinja2.ext import Extension
class DependenciesExt(Extension):
"""This extension attempts to track the dependencies used in a template."""
def filter_stream(self, stream):
current_token = None
for token in stream:
if not current_token:
if token.type == 'name':
if token.value in ['include', 'extends']:
current_token = token.value
print 'start: {}'.format(token.value)
elif current_token == 'include':
if token.type == 'name':
print '{} :: {}'.format(current_token, token.value)
current_token = None
if token.type == 'block_end':
current_token = None
elif current_token == 'extends':
if token.type == 'string':
print '{} :: {}'.format(current_token, token.value)
current_token = None
yield token
if __name__ == "__main__":
base_path = os.path.dirname(os.path.realpath(__file__))
jinja_env = jinja2.Environment(
loader=jinja2.FileSystemLoader(base_path))
template = jinja_env.get_template('template.html')
print template.render({
"partials": [
"test1.html",
"test2.html",
],
})
{% for partial in partials %}
{% include partial %}
{% endfor %}
@meritasix
Copy link

meritasix commented Jan 13, 2019

I've actually managed to pull this (or very close) off using jinja2.meta.find_referenced_templates(), overriding my fsloader and intercepting the source there. A working (and ugly) example:

class MFSLoader(FileSystemLoader):
	dependencies = {}
	def get_source(self, environment, template):
		source, filename, uptodate = super(MFSLoader, self).get_source(environment, template)
		dependencies = jinjameta.find_referenced_templates(environment.parse(source))
		if filename not in dependencies:
			self.dependencies[filename] = set()
		self.dependencies[filename].update(dependencies)
		return source, filename, uptodate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment