Skip to content

ratchet(types): type connector surface on model mixins + fix tag None-safety#1287

Merged
tomchop merged 1 commit into
mainfrom
ratchet/mixin-connector-types
Jul 13, 2026
Merged

ratchet(types): type connector surface on model mixins + fix tag None-safety#1287
tomchop merged 1 commit into
mainfrom
ratchet/mixin-connector-types

Conversation

@tomchop

@tomchop tomchop commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

First ty ratchet PR (follows #1286).

What

The YetiTagModel / YetiContextModel / YetiAclModel mixins call self.save(), self.neighbors(), self.extended_id — provided at runtime by ArangoYetiConnector (mixed into every persisted subclass), but invisible to the type checker within the mixins themselves. This is the single biggest source of ty's unresolved-attribute warnings.

YetiBaseModel can't actually inherit AbstractYetiConnector — that would make non-persisted models like YetiTagInstance abstract/uninstantiable. So the fix is TYPE_CHECKING-only stubs on YetiBaseModel. Runtime is completely unchanged — frontend-safe, no wire/OpenAPI impact.

Bug fixed

ty surfaced a real latent crash: Tag.find() returns Tag | None, but the tag-removal (clear=True) and clear_tags() paths dereferenced it (.count/.save) with no None check — a crash if the tag row is ever missing. Now skips when absent.

Effect

  • core/schemas/model.py: 13 ty diagnostics → 0.
  • Total ty warnings across core/: 296 → 268; unresolved-attribute: 138 → 119.
  • ty exits 0 (no new error-level diagnostics); all three unittest suites pass; ruff clean.

Not flipping any rule to error yet — unresolved-attribute still has ~119 instances (union-attribute access + other Optional cases) that later ratchet PRs will chip away at.

…one-safety

The YetiTagModel/YetiContextModel/YetiAclModel mixins call self.save() /
self.neighbors() / self.extended_id, which are provided at runtime by
ArangoYetiConnector (mixed into every persisted subclass) but are invisible to
the type checker within the mixins themselves. Declare them as TYPE_CHECKING-only
stubs on YetiBaseModel so ty can resolve them. Runtime is unchanged.

Also fixes a real latent crash ty surfaced: Tag.find() returns Tag | None, but
the tag-removal and clear_tags paths dereferenced it (.count/.save) without a
None check. Skip when the tag row is absent.

model.py goes from 13 ty diagnostics to 0.
@tomchop tomchop merged commit 50e8761 into main Jul 13, 2026
4 checks passed
@tomchop tomchop deleted the ratchet/mixin-connector-types branch July 13, 2026 18:01
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.

1 participant