# purity URL: /api/analysis/purity/ Section: analysis -------------------------------------------------------------------------------- purity - Kida window.BENGAL_THEME_DEFAULTS = { appearance: 'light', palette: 'brown-bengal' }; window.Bengal = window.Bengal || {}; window.Bengal.enhanceBaseUrl = '/kida/assets/js/enhancements'; window.Bengal.watchDom = true; window.Bengal.debug = false; window.Bengal.enhanceUrls = { 'toc': '/kida/assets/js/enhancements/toc.632a9783.js', 'docs-nav': '/kida/assets/js/enhancements/docs-nav.57e4b129.js', 'tabs': '/kida/assets/js/enhancements/tabs.aac9e817.js', 'lightbox': '/kida/assets/js/enhancements/lightbox.1ca22aa1.js', 'interactive': '/kida/assets/js/enhancements/interactive.fc077855.js', 'mobile-nav': '/kida/assets/js/enhancements/mobile-nav.d991657f.js', 'action-bar': '/kida/assets/js/enhancements/action-bar.d62417f4.js', 'copy-link': '/kida/assets/js/enhancements/copy-link.7d9a5c29.js', 'data-table': '/kida/assets/js/enhancements/data-table.1f5bc1eb.js', 'lazy-loaders': '/kida/assets/js/enhancements/lazy-loaders.a5c38245.js', 'holo': '/kida/assets/js/enhancements/holo.ee13c841.js', 'link-previews': '/kida/assets/js/enhancements/link-previews.8d906535.js' }; (function () { try { var defaults = window.BENGAL_THEME_DEFAULTS || { appearance: 'system', palette: '' }; var defaultAppearance = defaults.appearance; if (defaultAppearance === 'system') { defaultAppearance = (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light'; } var storedTheme = localStorage.getItem('bengal-theme'); var storedPalette = localStorage.getItem('bengal-palette'); var theme = storedTheme ? (storedTheme === 'system' ? defaultAppearance : storedTheme) : defaultAppearance; var palette = storedPalette ?? defaults.palette; document.documentElement.setAttribute('data-theme', theme); if (palette) { document.documentElement.setAttribute('data-palette', palette); } } catch (e) { document.documentElement.setAttribute('data-theme', 'light'); } })(); { "prerender": [ { "where": { "and": [ { "href_matches": "/docs/*" }, { "not": { "selector_matches": "[data-external], [target=_blank], .external" } } ] }, "eagerness": "conservative" } ], "prefetch": [ { "where": { "and": [ { "href_matches": "/*" }, { "not": { "selector_matches": "[data-external], [target=_blank], .external" } } ] }, "eagerness": "conservative" } ] } Skip to main content Magnifying Glass ESC Recent Clear Magnifying Glass No results for "" Start typing to search... ↑↓ Navigate ↵ Open ESC Close Powered by Lunr )彡 DocumentationInfoAboutArrow ClockwiseGet StartedCodeSyntaxTerminalUsageNoteTutorialsStarburstExtendingBookmarkReferenceTroubleshootingReleasesDevGitHubKida API Reference Magnifying Glass Search ⌘K Palette Appearance Chevron Down Mode Monitor System Sun Light Moon Dark Palette Snow Lynx Brown Bengal Silver Bengal Charcoal Bengal Blue Bengal List )彡 Magnifying Glass Search X Close Documentation Caret Down Info About Arrow Clockwise Get Started Code Syntax Terminal Usage Note Tutorials Starburst Extending Bookmark Reference Troubleshooting Releases Dev Caret Down GitHub Kida API Reference Palette Appearance Chevron Down Mode Monitor System Sun Light Moon Dark Palette Snow Lynx Brown Bengal Silver Bengal Charcoal Bengal Blue Bengal Kida API Reference Caret Right Analysis analyzer cache config dependencies landmarks metadata purity roles Caret Right Compiler Caret Right Statements basic control_flow functions special_blocks template_structure variables _protocols coalescing core expressions utils Caret Right Environment core exceptions filters loaders protocols registry tests Caret Right Parser Caret Right Blocks control_flow core functions special_blocks template_structure variables _protocols core errors expressions statements tokens Caret Right Utils html lru_cache workers _types bytecode_cache kida lexer nodes template tstring Kida API ReferenceAnalysis ᗢ Caret Down Link Copy URL External Open LLM text Copy Copy LLM text Share with AI Ask Claude Ask ChatGPT Ask Gemini Ask Copilot 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. 1Class1Function Classes PurityAnalyzer 45 ▼ 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. 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 44 ▼ __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: 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 _visit 1 PurityLevel ▼ Visit a node and determine purity. def _visit(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_children 1 PurityLevel ▼ Visit children and combine purity. def _visit_children(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_const 1 PurityLevel ▼ Constants are pure. def _visit_const(self, node: Any) -> 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: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_getattr 1 PurityLevel ▼ Attribute access is pure. def _visit_getattr(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_optionalgetattr 1 PurityLevel ▼ Optional attribute access is pure. def _visit_optionalgetattr(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_getitem 1 PurityLevel ▼ Subscript access is pure. def _visit_getitem(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_optionalgetitem 1 PurityLevel ▼ Optional subscript access is pure. def _visit_optionalgetitem(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_binop 1 PurityLevel ▼ Binary operations are pure. def _visit_binop(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_unaryop 1 PurityLevel ▼ Unary operations are pure. def _visit_unaryop(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_compare 1 PurityLevel ▼ Comparisons are pure. def _visit_compare(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_boolop 1 PurityLevel ▼ Boolean operations are pure. def _visit_boolop(self, node: Any) -> 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: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_nullcoalesce 1 PurityLevel ▼ Null coalescing is pure. def _visit_nullcoalesce(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_concat 1 PurityLevel ▼ String concatenation is pure. def _visit_concat(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_range 1 PurityLevel ▼ Range literals are pure. def _visit_range(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_slice 1 PurityLevel ▼ Slice expressions are pure. def _visit_slice(self, node: Any) -> 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: Any) -> 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: Any) -> 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: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_filter 1 PurityLevel ▼ Filter purity depends on the filter. def _visit_filter(self, node: Any) -> 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: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_funccall 1 PurityLevel ▼ Function call purity depends on the function. def _visit_funccall(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_test 1 PurityLevel ▼ Tests are pure (they're just predicates). def _visit_test(self, node: Any) -> 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: Any) -> 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: Any) -> 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: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_output 1 PurityLevel ▼ Output is pure if expression is pure. def _visit_output(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_data 1 PurityLevel ▼ Static data is pure. def _visit_data(self, node: Any) -> 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: Any) -> 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: Any) -> 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: Any) -> 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: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_set 1 PurityLevel ▼ Set is pure if value is pure. def _visit_set(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_let 1 PurityLevel ▼ Let is pure if value is pure. def _visit_let(self, node: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_capture 1 PurityLevel ▼ Capture is pure if body is pure. def _visit_capture(self, node: Any) -> 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: Any) -> 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: Any) -> 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: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_macro 1 PurityLevel ▼ Macro definition (same as def). def _visit_macro(self, node: Any) -> 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: Any) -> PurityLevel Parameters Name Type Description node — Returns PurityLevel _visit_marksafe 1 PurityLevel ▼ Mark safe is pure. def _visit_marksafe(self, node: Any) -> 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: Any) -> 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 ← Previous metadata Next → roles List © 2026 Kida built in ᓚᘏᗢ { "linkPreviews": { "enabled": true, "hoverDelay": 200, "hideDelay": 150, "showSection": true, "showReadingTime": true, "showWordCount": true, "showDate": true, "showTags": true, "maxTags": 3, "includeSelectors": [".prose"], "excludeSelectors": ["nav", ".toc", ".breadcrumb", ".pagination", ".card", "[class*='-card']", ".tab-nav", "[class*='-widget']", ".child-items", ".content-tiles"], "allowedHosts": [], "allowedSchemes": ["https"], "hostFailureThreshold": 3 } } window.BENGAL_LAZY_ASSETS = { tabulator: '/kida/assets/js/tabulator.min.js', dataTable: '/kida/assets/js/data-table.js', mermaidToolbar: '/kida/assets/js/mermaid-toolbar.9de5abba.js', mermaidTheme: '/kida/assets/js/mermaid-theme.344822c5.js', graphMinimap: '/kida/assets/js/graph-minimap.ff04e939.js', graphContextual: '/kida/assets/js/graph-contextual.355458ba.js' }; window.BENGAL_ICONS = { close: '/kida/assets/icons/close.911d4fe1.svg', enlarge: '/kida/assets/icons/enlarge.652035e5.svg', copy: '/kida/assets/icons/copy.3d56e945.svg', 'download-svg': '/kida/assets/icons/download.04f07e1b.svg', 'download-png': '/kida/assets/icons/image.c34dfd40.svg', 'zoom-in': '/kida/assets/icons/zoom-in.237b4a83.svg', 'zoom-out': '/kida/assets/icons/zoom-out.38857c77.svg', reset: '/kida/assets/icons/reset.d26dba29.svg' }; Arrow Up -------------------------------------------------------------------------------- Metadata: - Word Count: 1850 - Reading Time: 9 minutes