Repository navigation
Iterate a list or tuple subclass as Python does (0441) - #827
Conversation
IHostObject::IteratesByIndex() (true by default) lets a sequence say that iter(x) differs from its items by index. The bridge then iterates it through Iterate instead of Len and ItemAtTo. PyHost answers false for a list or tuple subclass that overrides __iter__, so a loop over it goes through __iter__ as in Jinja2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AWNL7mqnaXzqZnVND5kuSG
A subclass that overrides only __getitem__ looped through it, while Python's list iterator reads the list's own items. The Python rows are built afresh per engine: a deep copy of a list subclass is rebuilt from its __iter__ and hid the case. Filed 0452 for loop.length and operators. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AWNL7mqnaXzqZnVND5kuSG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AWNL7mqnaXzqZnVND5kuSG
|
@codex review Generated by Claude Code |
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 330371990d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…441) Codex on #827: a list subclass iterated through its __iter__ lost loop.length (Jinja2 takes len(iterable)) and + * < and str % read the iterated items. A loop over a host object now takes its length from Len when first read, and host::AsSequence reads the new private IEngineHostObject::SequenceItems, by index. 0453 narrows to pprint. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AWNL7mqnaXzqZnVND5kuSG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AWNL7mqnaXzqZnVND5kuSG
|
@codex review Generated by Claude Code |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DTQTriEsFrrBgcYNKDUUF4
Mark 0441 done after #827; sync index and G1 row
Requested by Ruslan · project thread
Problem
Since 0357 S3 the Python module goes through the public host-object contract. That contract iterates every
IsSequenceobject that has aLenby index (HostSequenceList:Len+ItemAtTo). Alistsubclass that overrides__iter__therefore looped over its stored items:The verifier found a second case. A subclass that overrides only
__getitem__looped through that override (GGG), but Python's list iterator ignores it and gives123.Change
IHostObject::IteratesByIndex(), true by default.EngineBridge::IterateusesHostSequenceListonly when it returns true. Otherwise it goes throughIterate. This adds a vtable slot before the G1 freeze, as the backlog report recommended, and is recorded in docs/api-2.0.md section 7 item 10.PyHost::IteratesByIndexis true only for an exactlistortuple. A subclass is iterated throughiter(): its own__iter__if it has one, otherwise the base type's iterator, which is also live. The exact-type fast path is unchanged.+,*, comparisons andstr % xkeep reading the stored items, as Python's list operations do.host::AsSequencenow reads a new privateIEngineHostObject::SequenceItems(), which the bridge answers by index.loop.length. A loop over any host object takesloop.length(andrevindex) from the object'sLenwhen the template first reads it, as Jinja2 takeslen(iterable)(SetLengthOfValue, src/statements.cpp). It falls back to counting the items when the object has no length.loop.laststill comes from peeking.Validation
PublicHostObjectTest.SequenceThatIteratesByItsOwnIteratecovers a C++ host with its ownIterate,Len3 and 2 iterated items: the loop,loop.length,last,+and*, narrow and wide.python/tests/test_values.py::test_list_and_tuple_subclasses_iterate_as_python_doeshas 8 rows. They cover__iter__and__getitem__overrides, a plain subclass, a non-sequence with__len__, theloopattributes and the operators.render_both's deepcopy rebuilds a list subclass from its__iter__and would hide the case (verifier F1).IteratesByIndexforced true, 4 of the first 5 rows fail.python/testsgives 1629 passed, 17 skipped, 2 xfailed.scripts/preflight.sh --perfpasses. The instruction gate shows at most +0.06%, on mitsuhiko_table.Remaining limits
Task 0453:
l|pprintof such a subclass prints its stored items, while Jinja2'spprintiterates it. It printed the same way before this PR. The task was first numbered 0452, but another thread took that number at the same time.Roles: verifier, 1 round (F1 and F3 fixed, F2 and F4 first filed, then fixed after Codex). Red CI pushes: none so far.
Codex: 2 findings (P2), 2 fixed, 0 declined. Security review: not needed. The diff touches the host-object bridge and the loop's length source, not the lexer, parsers, loaders, escaping or the sandbox.
🤖 Generated with Claude Code
https://claude.ai/code/session_01AWNL7mqnaXzqZnVND5kuSG