Repository navigation
Check objects and call arguments as Jinja2 does (0197, 0206) - #552
Merged
Merged
Conversation
truncate takes len() of any value and urlencode quotes an object's repr; a tuple assignment from a dict unpacks its keys (host objects keep the by-name extension); lipsum, attr, joiner and cycler methods check their arguments; map reports the named filter's argument error; range and the comparison tests reject keyword arguments. The unread-select case becomes a deliberate divergence under 0101; object dict keys and objects through user callables are filed as 0210. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HFw7ujEwV7pcqD96PpJnDR
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HFw7ujEwV7pcqD96PpJnDR
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HFw7ujEwV7pcqD96PpJnDR
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HFw7ujEwV7pcqD96PpJnDR
…o range Fixes found by the verifier: truncate rejects an end with no len() and checks length >= len(end) for an undefined value too; lipsum with no paragraphs no longer checks min < max. The JSON-object unpacking finding goes to 0210. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HFw7ujEwV7pcqD96PpJnDR
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HFw7ujEwV7pcqD96PpJnDR
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HFw7ujEwV7pcqD96PpJnDR
rmorozov
marked this pull request as ready for review
October 17, 2026 17:52
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.
Requested by Ruslan · project thread
Before:
cycler(1, 2)|truncaterendered empty.namespace(a=1)|urlencodegavea=1.{% set a, b = {'x': 1, 'y': 2} %}took the items namedaandb, so both were empty. A number of calls that Python rejects also rendered:range(stop=2),['a']|map('upper', 1),ns|attr('a', 'b'),ns|attr(1),joiner('a')('x'),lipsum(namespace())and1 is eq(b=1).After: each of these behaves as in Jinja2 3.1.6. The tuple assignment unpacks the dict's keys (
xy), and every other call raises the TypeError Python raises.The changes:
do_truncate. A value with nolen()raises (None, a bool, a number, an object). A short list or dict comes back as itself. A long one fails where Python's string code fails.endmust have alen(), and an undefined checkslength >= len(end)too.namespace().GenericMap) keeps the old by-name extension, because Python could not unpack it at all.nis an integer, and checksminandmaxwhen it makes a paragraph.next()andreset().default=stays a keyword-only Jinja2C++ extension.eq,lt, …) reject keyword arguments.Deliberate divergences:
tests.select_unread_extra_argis now a deliberate divergence under 0101.selectstays eager, which is the same model asfilters.select_single_pass.range()with no arguments still renders empty, as before.Filed 0212 for what 0197 could not reach:
globals.object_dict_key.How: the corpus lines for 0197 and 0206 are deleted from
test/parity/divergences/. New corpus cases cover each behaviour that had none. Unit tests that encoded the old behaviour were updated:forloop_test.cpp, the range keyword rows are gone.SetTest.Tuple1AssignmentTestnow expects the keys.Roles: verifier (1 round, which found 1 blocking issue: a missing include flagged by clang-tidy, fixed). Its non-blocking findings were fixed here (truncate
end/undefined,lipsum(0)) or filed in 0212.scripts/preflight.sh --perfis clean; the worst benchmark moved +1.58% (Render/strings). Red pushes: none yet.Generated by Claude Code