Skip to content

A view declares what it shows as a class keyword; the family is the tree below it - #19

Merged
trissim merged 3 commits into
mainfrom
refactor/shows-is-a-declaration
Nov 6, 2026
Merged

trissim merged 3 commits into
mainfrom
refactor/shows-is-a-declaration

Conversation

@trissim

@trissim trissim commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

DeclaredViews stops probing class bodies. 2 commits, 1 source file, plus a new behaviour test.

Why

Membership was decided by vars(cls).get("shows", ()), a structural probe for whether a name appears in a class body, with a default when it doesn't. A hand-built shown_by registry per family root was found by DeclaredViews in cls.__bases__. Whether an abstract family root (Toad's FieldView, now abstract via toad#1542) could ever be returned by showing() therefore rested on an absence: that its body didn't happen to say shows. Paper1 Proposition 3.3: structural membership admits by shape; nominal admission follows declared edges.

Before / after

  • Before: shows = (int,) in the class body; registry dict built in __init_subclass__; family root found by base-list inspection.
  • After: class IntEditor(ValueEditor, shows=(int,)). The mixin's __init_subclass__(cls, *, shows=(), **kw) records it on every class (default ()), so a parent's declaration never passes to a child. showing() walks members(), the inheritance tree below the class asked. Deleted: shown_by, the vars() probe and the __bases__ check.
  • A family root lists DeclaredViews before its widget base so the keyword is taken before a framework's __init_subclass__ (Textual's DOMNode rejects unknown keywords).

Proof

tests/test_declared_views.py: the first declaration with a member wins (MRO order); a subclass declaring nothing shows nothing; an unshown declaration raises LookupError; a sub-family answers from its own subtree. 8 passed with tests/test_declared_fields.py.

Lands with

Toad's members move to the keyword in a paired Toad PR. Toad is the only consumer (checked across the local projects, OpenHCS included). Formbridge first, then Toad and the stack relock.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XbFMSqJMarXn2ZE8iAL7Sd

trissim and others added 2 commits November 5, 2026 23:09
…ree below it

DeclaredViews decided membership by probing a class body for a name,
`vars(cls).get("shows", ())`, and kept a hand-built `shown_by` registry per
family root found by `DeclaredViews in cls.__bases__`. Both are structural tests
of a class's shape. A body without `shows` was silently "not a member", so whether
an abstract family root could be returned by showing() rested on an absence
(paper1 Proposition 3.3: structural membership admits by shape, nominal
admission follows declared edges).

Now `shows` is a class keyword taken by the mixin's __init_subclass__ and recorded
on every class, default (), so a parent's declaration never passes to a child.
showing() walks the inheritance tree below the class asked. The registry and the
family-root base-list check are deleted: the hierarchy already says which
members a family has.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XbFMSqJMarXn2ZE8iAL7Sd
…s taken first

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XbFMSqJMarXn2ZE8iAL7Sd
Copilot AI balanced review requested due to automatic review settings November 6, 2026 04:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

… outside a family

Toad stuffed a lambda into ValueEditor.shown_by from module scope so a field
with prepared choices would be edited by whatever its prepared parameter names.
That was a registry entry written outside any class. Now annotation metadata
may inherit DeclaredMetadata and override declares(); declarations() classifies
each foreign metadata item once, by singledispatch on its type, at this boundary.
By default an item still declares its class and that class's bases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XbFMSqJMarXn2ZE8iAL7Sd
@trissim
trissim merged commit 0547625 into main Nov 6, 2026
11 of 13 checks passed
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.

2 participants