Module

analysis.purity

Purity analysis for template introspection.

Determines if expressions and blocks are pure (deterministic). Pure blocks produce the same output for the same inputs.

Classes

PurityAnalyzer 48 ▼
Determine if an expression or block is pure (deterministic). Pure expressions produce the same out…

Determine if an expression or block is pure (deterministic).

Pure expressions produce the same output for the same inputs. This is used to determine cache safety.

Conservative: defaults to "unknown" when uncertain.

Thread-safe:analyze()isolates circular-include tracking in a ContextVar, so one analyzer may be shared across concurrent calls.

Purity Rules:

  • Constants, variables, attribute access: pure
  • Binary/unary operations, comparisons: pure
  • Known pure filters (upper, lower, sort, etc.): pure
  • Known impure filters (random, shuffle): impure
  • Unknown filters/functions: unknown

Methods

analyze 1 PurityLevel ▼
Analyze a node and return its purity level.
def analyze(self, node: Node) -> PurityLevel
Parameters
Name Type Description
node —

AST node to analyze.

Returns
PurityLevel "pure", "impure", or "unknown"
Internal Methods 47 ▼
__init__ 3 ▼
Initialize analyzer with optional extensions.
def __init__(self, extra_pure_functions: frozenset[str] | None = None, extra_impure_filters: frozenset[str] | None = None, template_resolver: Callable[[str], Any] | None = None) -> None
Parameters
Name Type Description
extra_pure_functions —

Additional functions to treat as pure.

Default:None
extra_impure_filters —

Additional filters to treat as impure.

Default:None
template_resolver —

Optional callback(name: str) -> Template | None to resolve included templates. If None, includes return "unknown".

Default:None
_visited_for_call 0 set[str] ▼
Return circular-include state for this analysis context.
def _visited_for_call(self) -> set[str]
Returns
set[str]
_visit 1 PurityLevel ▼
Visit a node and determine purity.
def _visit(self, node: Node | None) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_children 1 PurityLevel ▼
Visit children and combine purity.
def _visit_children(self, node: Node) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_const 1 PurityLevel ▼
Constants are pure.
def _visit_const(self, node: Const) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_name 1 PurityLevel ▼
Variable access is pure (reading doesn't mutate).
def _visit_name(self, node: Name) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_getattr 1 PurityLevel ▼
Attribute access is pure.
def _visit_getattr(self, node: Getattr) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_optionalgetattr 1 PurityLevel ▼
Optional attribute access is pure.
def _visit_optionalgetattr(self, node: OptionalGetattr) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_getitem 1 PurityLevel ▼
Subscript access is pure.
def _visit_getitem(self, node: Getitem) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_optionalgetitem 1 PurityLevel ▼
Optional subscript access is pure.
def _visit_optionalgetitem(self, node: OptionalGetitem) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_binop 1 PurityLevel ▼
Binary operations are pure.
def _visit_binop(self, node: BinOp) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_unaryop 1 PurityLevel ▼
Unary operations are pure.
def _visit_unaryop(self, node: UnaryOp) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_compare 1 PurityLevel ▼
Comparisons are pure.
def _visit_compare(self, node: Compare) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_boolop 1 PurityLevel ▼
Boolean operations are pure.
def _visit_boolop(self, node: BoolOp) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_condexpr 1 PurityLevel ▼
Conditional expressions are pure if all parts are pure.
def _visit_condexpr(self, node: CondExpr) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_nullcoalesce 1 PurityLevel ▼
Null coalescing is pure.
def _visit_nullcoalesce(self, node: NullCoalesce) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_concat 1 PurityLevel ▼
String concatenation is pure.
def _visit_concat(self, node: Concat) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_range 1 PurityLevel ▼
Range literals are pure.
def _visit_range(self, node: Range) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_slice 1 PurityLevel ▼
Slice expressions are pure.
def _visit_slice(self, node: Slice) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_list 1 PurityLevel ▼
List literals are pure if all items are pure.
def _visit_list(self, node: List) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_listcomp 1 PurityLevel ▼
List comprehensions are pure if iter, elt, and ifs are all pure.
def _visit_listcomp(self, node: ListComp) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_tuple 1 PurityLevel ▼
Tuple literals are pure if all items are pure.
def _visit_tuple(self, node: Tuple) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_dict 1 PurityLevel ▼
Dict literals are pure if all keys and values are pure.
def _visit_dict(self, node: Dict) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_filter 1 PurityLevel ▼
Filter purity depends on the filter.
def _visit_filter(self, node: Filter) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_pipeline 1 PurityLevel ▼
Pipeline purity depends on all filters in the chain.
def _visit_pipeline(self, node: Pipeline) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_funccall 1 PurityLevel ▼
Function call purity depends on the function.
def _visit_funccall(self, node: FuncCall) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_test 1 PurityLevel ▼
Tests are pure (they're just predicates).
def _visit_test(self, node: Test) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_for 1 PurityLevel ▼
For loops are pure if body is pure.
def _visit_for(self, node: For) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_if 1 PurityLevel ▼
Conditionals are pure if all branches are pure.
def _visit_if(self, node: If) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_match 1 PurityLevel ▼
Match statements are pure if all branches are pure.
def _visit_match(self, node: Match) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_output 1 PurityLevel ▼
Output is pure if expression is pure.
def _visit_output(self, node: Output) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_data 1 PurityLevel ▼
Static data is pure.
def _visit_data(self, node: Data) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_cache 1 PurityLevel ▼
Cache blocks: the body is evaluated, but result is cached. The block itself is…
def _visit_cache(self, node: Cache) -> PurityLevel

Cache blocks: the body is evaluated, but result is cached.

The block itself is pure if the body is pure.

Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_block 1 PurityLevel ▼
Block is pure if body is pure.
def _visit_block(self, node: Block) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_with 1 PurityLevel ▼
With blocks are pure if bindings and body are pure.
def _visit_with(self, node: With) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_withconditional 1 PurityLevel ▼
Conditional with is pure if expr and body are pure.
def _visit_withconditional(self, node: WithConditional) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_set 1 PurityLevel ▼
Set is pure if value is pure.
def _visit_set(self, node: Set) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_let 1 PurityLevel ▼
Let is pure if value is pure.
def _visit_let(self, node: Let) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_capture 1 PurityLevel ▼
Capture is pure if body is pure.
def _visit_capture(self, node: Capture) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_include 1 PurityLevel ▼
Include purity depends on included template. If template_resolver is provided …
def _visit_include(self, node: Include) -> PurityLevel

Include purity depends on included template.

If template_resolver is provided and template name is a constant, resolves and analyzes the included template. Otherwise returns "unknown".

Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_extends 1 PurityLevel ▼
Extends is unknown (depends on parent template).
def _visit_extends(self, node: Extends) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_def 1 PurityLevel ▼
Function definition is pure if body is pure.
def _visit_def(self, node: Def) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_macro 1 PurityLevel ▼
Macro definition (same as def).
def _visit_macro(self, node: Def) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_inlinedfilter 1 PurityLevel ▼
Inlined filter is pure (only pure filters are inlined).
def _visit_inlinedfilter(self, node: InlinedFilter) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_marksafe 1 PurityLevel ▼
Mark safe is pure.
def _visit_marksafe(self, node: MarkSafe) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_await 1 PurityLevel ▼
Await is unknown (async operations may have side effects).
def _visit_await(self, node: Await) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel
_visit_trans 1 PurityLevel ▼
Trans blocks are impure — gettext/ngettext depend on locale state.
def _visit_trans(self, node: Trans) -> PurityLevel
Parameters
Name Type Description
node —
Returns
PurityLevel

Functions

_combine_purity 2 PurityLevel ▼
Combine two purity levels (take worst case).
def _combine_purity(a: PurityLevel, b: PurityLevel) -> PurityLevel
Parameters
Name Type Description
a PurityLevel
b PurityLevel
Returns
PurityLevel