0
# Meta Analysis
1
2
Template introspection functions for analyzing template dependencies and variable usage. Useful for dependency tracking, caching systems, and development tools.
3
4
## Capabilities
5
6
### Variable Analysis
7
8
Analyze templates to find all variables that will be looked up from the context at runtime.
9
10
```python { .api }
11
def find_undeclared_variables(ast):
12
"""
13
Returns a set of all variables in the AST that will be looked up from
14
the context at runtime.
15
16
Because at compile time it's not known which variables will be used
17
depending on the path the execution takes at runtime, all variables
18
are returned.
19
20
Parameters:
21
ast: Template AST node from Environment.parse()
22
23
Returns:
24
set: Set of variable names that will be looked up from context
25
26
Raises:
27
TemplateAssertionError: During compilation if template is invalid
28
"""
29
```
30
31
### Template Dependency Analysis
32
33
Find all templates referenced by extends, includes, and imports in a template.
34
35
```python { .api }
36
def find_referenced_templates(ast):
37
"""
38
Finds all the referenced templates from the AST.
39
40
Returns an iterator over all the hardcoded template extensions, inclusions
41
and imports. If dynamic inheritance or inclusion is used, None will be
42
yielded for those entries.
43
44
Parameters:
45
ast: Template AST node from Environment.parse()
46
47
Yields:
48
str or None: Template names found, or None for dynamic references
49
"""
50
```
51
52
## Usage Examples
53
54
### Finding Undeclared Variables
55
56
```python
57
from jinja2 import Environment, meta
58
59
env = Environment()
60
61
# Simple template with variables
62
template_source = '{{ user.name }} has {{ count }} items'
63
ast = env.parse(template_source)
64
variables = meta.find_undeclared_variables(ast)
65
print(variables) # {'user', 'count'}
66
67
# Template with loops and conditions
68
template_source = '''
69
{% for item in items %}
70
{{ item.name }} - {{ item.price }}
71
{% endfor %}
72
{% if total > 100 %}
73
Discount: {{ discount }}
74
{% endif %}
75
'''
76
ast = env.parse(template_source)
77
variables = meta.find_undeclared_variables(ast)
78
print(variables) # {'items', 'total', 'discount'}
79
```
80
81
### Finding Template Dependencies
82
83
```python
84
from jinja2 import Environment, meta
85
86
env = Environment()
87
88
# Template with static dependencies
89
template_source = '''
90
{% extends "base.html" %}
91
{% include "header.html" %}
92
{% from "macros.html" import button %}
93
'''
94
ast = env.parse(template_source)
95
dependencies = list(meta.find_referenced_templates(ast))
96
print(dependencies) # ['base.html', 'header.html', 'macros.html']
97
98
# Template with dynamic dependencies
99
template_source = '''
100
{% extends layout_template %}
101
{% include "static.html" %}
102
{% include dynamic_include %}
103
'''
104
ast = env.parse(template_source)
105
dependencies = list(meta.find_referenced_templates(ast))
106
print(dependencies) # [None, 'static.html', None]
107
```
108
109
### Dependency Tracking System
110
111
```python
112
from jinja2 import Environment, meta
113
import os
114
115
def analyze_template_dependencies(template_path):
116
"""Analyze a template file and return its variable and template dependencies."""
117
env = Environment()
118
119
with open(template_path) as f:
120
source = f.read()
121
122
ast = env.parse(source)
123
124
# Find variables needed from context
125
variables = meta.find_undeclared_variables(ast)
126
127
# Find referenced templates
128
templates = [t for t in meta.find_referenced_templates(ast) if t is not None]
129
130
return {
131
'variables': variables,
132
'templates': templates,
133
'has_dynamic_dependencies': None in meta.find_referenced_templates(ast)
134
}
135
136
# Example usage
137
dependencies = analyze_template_dependencies('templates/user_profile.html')
138
print(f"Variables needed: {dependencies['variables']}")
139
print(f"Template dependencies: {dependencies['templates']}")
140
print(f"Has dynamic deps: {dependencies['has_dynamic_dependencies']}")
141
```
142
143
### Template Variable Validation
144
145
```python
146
from jinja2 import Environment, meta
147
148
def validate_template_context(template_source, provided_context):
149
"""Validate that all required variables are provided in context."""
150
env = Environment()
151
ast = env.parse(template_source)
152
required_vars = meta.find_undeclared_variables(ast)
153
154
missing_vars = required_vars - set(provided_context.keys())
155
156
if missing_vars:
157
raise ValueError(f"Missing required variables: {missing_vars}")
158
159
return True
160
161
# Example usage
162
template = "Hello {{ name }}, you have {{ count }} messages"
163
context = {"name": "Alice", "count": 5}
164
165
try:
166
validate_template_context(template, context)
167
print("All variables provided!")
168
except ValueError as e:
169
print(f"Validation error: {e}")
170
```
171
172
### Build System Integration
173
174
```python
175
from jinja2 import Environment, meta
176
import os
177
from pathlib import Path
178
179
def get_template_dependency_graph(template_dir):
180
"""Build dependency graph for all templates in a directory."""
181
env = Environment()
182
dependency_graph = {}
183
184
for template_file in Path(template_dir).glob('**/*.html'):
185
template_path = str(template_file.relative_to(template_dir))
186
187
with open(template_file) as f:
188
source = f.read()
189
190
ast = env.parse(source)
191
dependencies = [
192
dep for dep in meta.find_referenced_templates(ast)
193
if dep is not None
194
]
195
196
dependency_graph[template_path] = dependencies
197
198
return dependency_graph
199
200
# Example usage for build system
201
deps = get_template_dependency_graph('templates/')
202
for template, dependencies in deps.items():
203
print(f"{template} depends on: {dependencies}")
204
```
205
206
## Import Pattern
207
208
```python
209
from jinja2 import meta
210
211
# Access meta functions through the meta module
212
variables = meta.find_undeclared_variables(ast)
213
templates = meta.find_referenced_templates(ast)
214
```