Repository navigation
fix: keep the parent block's filters when a child renders block.super - #187
Merged
Merged
Conversation
…ocessor A TEMPLATES bound in a function, called or not, or in a class configures nothing; a function reading, mutating or rebinding the module's TEMPLATES leaves the activation uncertain; a local TEMPLATES beside module settings changes nothing.
request_processor walked every node of every module and counted any assignment to TEMPLATES, so a function-local or class-level assignment activated the request context processor. It now walks the modules with their scope tables: an assignment counts only at module scope, and a mention counts only when the name resolves to the module's binding, or to nothing, as a star import gives. ScopeTable.scope_for accepts a lambda, whose scope the builder already records.
…e flow
A block rendering {{ block.super }} extends the parent's block: its filters stay fed by the render context, with the parent template as the place of the call, however block.super is rendered; a block without it replaces the parent's whole block; other overridden blocks stay excluded; a chain of templates keeps exactly the parents each level renders, once.
A template extending another replaced every block it defined in the parent, so the parent's filter applications dropped out of the render context flow even when the child rendered {{ block.super }}, which Django executes. A template now records the blocks that render block.super, and only the blocks defined without it are passed up as replaced, level by level.
# Conflicts: # CHANGELOG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #185.
Summary
{{ block.super }}, which Django executes. The reachable finding at the parent's line was kept; the exploitable flow was lost._read_scopesnow records the blocks whose body rendersblock.super(_Template.extended), and_reachingpasses up as replaced only the blocks a template defines without it (_Template.replaced), level by level: a child withblock.superkeeps its parent's content; a parent that itself replaced its own parent's block still cuts the chain above it; a replacement at the end cuts the whole chain. Other overridden blocks stay excluded, and each application is yielded once, with the parent template asthroughand the filter's line assink_line.block.supercounts however the block renders it: filtered, conditional or twice.Verification
tests/test_block_super.py: 10 passed; the context-flow, filter-call and docs tests pass. Full suite in the worktree (regression excluded): all passed.ruff checkandmypypass.block.super; treating nothing as replaced (fails the existingoverridden-twicecase).