Skip to content

Keep every base's slots under multiple inheritance - #180

Merged
ESultanik merged 4 commits into
masterfrom
173-fix-slot-accumulation
Sep 9, 2026
Merged

ESultanik merged 4 commits into
masterfrom
173-fix-slot-accumulation

Conversation

@ESultanik

Copy link
Copy Markdown
Collaborator

Closes #173.

Builds on @Liyu0310-Code's work in #175, which was merged into this branch so their commit is carried over intact, and finishes it.

The bug

DataClassNode.__init_subclass__ accumulated slots by reading the inherited _SLOTS / _SLOT_ANNOTATIONS attributes, which resolve through the MRO to only the first inheritance chain. Under diamond inheritance the slots of every base after the first were silently dropped, so items(), __iter__, to_obj() and the hash all ignored them, and constructing the class failed with a misleading TypeError: object.__init__() takes exactly one argument.

The fix collects annotations from every data-class ancestor and derives _SLOTS from the merged mapping. The reproducer in #173 now gives:

D._SLOTS = ('a', 'c', 'b', 'd')
to_obj   = {'a': 1, 'c': 3, 'b': 2, 'd': 4}

What this branch corrects

df537d6 fixes two things in the merged change:

The ancestors were iterated in the wrong order. The slot merge was written against an earlier __init_subclass__, where ancestors was in plain __mro__ order and had to be reversed to merge base-first. #166 has since rebuilt that list from reversed(cls.__mro__), so it already arrives base-first, and reversing it again inverted the merge order — a diamond class D(B, C) came out in B-then-C order. None of the edited lines overlapped with #166's, so the change applied cleanly while its meaning changed underneath it, and test_multiple_inheritance failed on the merge commit. The test itself was right; only the implementation disagreed with it.

new_slots had become dead. Once _SLOTS is derived from the merged annotations, the list is written but never read. Ruff does not report it: F841 wants a local that is never referenced, and new_slots.append(...) counts as a reference.

Validation

  • test_multiple_inheritance fails on d7c0f6a (the merge of Fix DataClassNode slot accumulation under multiple inheritance #175) and passes here. Reinstating the extra reversed() reproduces the failure on this branch, so the test is pinned to the defect rather than passing incidentally.
  • uv run --frozen --extra dev pytest — 175 passed, 19 subtests
  • uv run --frozen --extra dev ruff check graphtage test docs bindist — clean
  • uv run --frozen --extra dev make -C docs html SPHINXOPTS="-W --keep-going" — build succeeded

The full suite passing matters here beyond the new test: every in-tree DataClassNode is constructed positionally by its builder, so a change to _SLOTS ordering would surface as widespread failures rather than quietly.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GypKU5KdLfs2Cf8kS2TzJa

Liyu0310-Code and others added 4 commits September 9, 2026 22:57
…eritance-slots

Fix DataClassNode slot accumulation under multiple inheritance
The slot accumulation added in the previous commit was written against an
earlier `__init_subclass__`, where `ancestors` was in plain `__mro__` order
and had to be reversed to merge annotations base-first. PR #166 has since
rebuilt that list from `reversed(cls.__mro__)`, so it already arrives
base-first and reversing it again inverted the merge order: a diamond
`class D(B, C)` produced slots in `B`-then-`C` order rather than the
declaration order the ancestors imply.

Because none of the edited lines overlapped, the change applied cleanly on
top of #166 while its meaning changed underneath it, and the accompanying
test failed on the merge commit.

Deriving `_SLOTS` from the merged annotations also left `new_slots` written
but never read. Ruff does not report it, because `new_slots.append(...)`
counts as a reference for F841.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GypKU5KdLfs2Cf8kS2TzJa
@ESultanik
ESultanik merged commit dbccbfb into master Sep 9, 2026
12 checks passed
@ESultanik
ESultanik deleted the 173-fix-slot-accumulation branch September 9, 2026 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DataClassNode silently drops slots under multiple inheritance

2 participants