Skip to content

Clear ty's 99 override errors - #976

Merged
ajslater merged 1 commit into
developfrom
ty-override-baseline
Oct 19, 2026
Merged

ajslater merged 1 commit into
developfrom
ty-override-baseline

Conversation

@ajslater

Copy link
Copy Markdown
Owner

Summary

make ty (ty 0.0.89) failed on develop with 99 diagnostics, all override checks. This PR gets it to pass without turning the rule off across the codebase.

False positives (84)

Every class Meta(<Base>.Meta) in codex/models and codex/serializers hits invalid-attribute-override because of a ty bug (astral-sh/ty#4711). A [[tool.ty.overrides]] block in pyproject.toml turns that rule off for those two trees only, the same approach comicbox 5.3.2 takes for its schemas. Views and everything else are still checked.

Real fixes (15)

  • permission_classes (7): AuthMixin declared Sequence[type[BasePermission]], narrower than DRF's Sequence[_PermissionClass], so every subclass that set its own permissions clashed with APIView. Switching the mixin to DRF's type fixes all seven. Three views drop the narrow annotation they had copied.
  • input_serializer_class (4): BrowserParamsView typed it as type[BrowserSettingsSerializerBase], but the choices, metadata and mtime views assign a superclass or sibling serializer. Widened it to their common base, BrowserFilterChoicesInputSerializer, which is all init_params uses. Subclasses now inherit that type instead of re-declaring it.
  • NULL_CODE (1): the mixin is typed int | str, because VuetifyCharField compares against a string.
  • content_negotiation_class (1): djangorestframework-stubs types it str | None, but DRF resolves the setting to a class at runtime, so codex's override is correct. It gets an ignore for both checkers, with the reason in a comment.
  • Volume.name, CustomCover.library (2): these change a field's type on purpose. The scoped override above also hides them. Adding ty: ignore comments now would itself fail make ty, since ty reports unused ignores as warnings, so the pyproject comment says to add them when the override is removed.

The fixes also made six pyright reportIncompatibleVariableOverride ignores unnecessary (AuthAPIView, AuthGenericAPIView, OpenSearch1View, the choices, metadata and mtime views, and VuetifyCharField), so they are removed.

Reviewer notes

  • Annotation-only change: no runtime behaviour changes.
  • make lint still shows two warnings: basedpyright reportUnreachable at codex/views/browser/annotate/cover.py:63 and :69. That branch is deliberately kept under its "PENDING SCHEMA REMOVAL" note so dynamic and custom covers can come back with a revert, so this PR leaves it alone.

Test plan

  • make fix: no changes beyond this diff
  • make lint: passes (only the two warnings above)
  • make ty: all checks passed
  • radon cc --min C and mi --min B on the changed files: empty; complexipy passes
  • make test: 1668 pytest passed, 1 xfailed; 994 vitest tests across 97 files passed

🤖 Generated with Claude Code

`make ty` (ty 0.0.89) failed with 99 diagnostics on develop.

False positives (84): every `class Meta(<Base>.Meta)` in codex/models and
codex/serializers trips invalid-attribute-override
(astral-sh/ty#4711). A [[tool.ty.overrides]]
block turns that rule off for those two trees only, as comicbox 5.3.2
does for its schemas. It also hides the deliberate Volume.name and
CustomCover.library overrides there; the pyproject comment says to mark
them with ty ignores when the block goes.

Real (15):
- permission_classes (7): AuthMixin declared
  Sequence[type[BasePermission]], narrower than DRF's
  Sequence[_PermissionClass], so every subclass that set its own classes
  clashed with APIView. Using DRF's type fixes all seven, lets three
  views drop their copied annotation, and retires three pyright
  reportIncompatibleVariableOverride ignores (AuthAPIView,
  AuthGenericAPIView, OpenSearch1View).
- input_serializer_class (4): BrowserParamsView typed it
  type[BrowserSettingsSerializerBase], yet choices, metadata and mtime
  set a superclass or sibling serializer. Widened to their common base,
  BrowserFilterChoicesInputSerializer, which is all init_params needs;
  subclasses now inherit the type, dropping three pyright ignores.
- NULL_CODE (1): the mixin is typed int | str, since VuetifyCharField
  compares against a str; drops a pyright ignore.
- content_negotiation_class (1): djangorestframework-stubs types it
  str | None, but DRF resolves the setting to a class, so the override
  is right; ignored for both checkers with that reason.
- Volume.name, CustomCover.library (2): deliberate type-changing model
  overrides, covered by the scoped override above.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ajslater
ajslater merged commit bbb0d1f into develop Oct 19, 2026
9 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.

1 participant