Skip to content

refactor(backend): convert models to Mapped and mapped_column - #114

Merged
klin2686 merged 3 commits into
mainfrom
refactor/models-mapped
Oct 13, 2026
Merged

klin2686 merged 3 commits into
mainfrom
refactor/models-mapped

Conversation

@klin2686

@klin2686 klin2686 commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Converts models.py from classic Column() to SQLAlchemy 2's typed Mapped[] / mapped_column() style, so model attributes have real types in Pylance and Pyright.

No schema or ORM behavior changes; verified by comparing a full snapshot of the mapping before and after.

What changed

Backend

Models and migrations

  • All 302 columns and 128 relationships converted; every SQL type stays explicit (needed for String(n), Text, DateTime(timezone=True) and JSON).
  • Nullability now lives only in the annotation (T | None); 231 nullable= arguments that repeated it are removed.
  • Annotations were generated from the live mapping (column nullability, list vs single for relationships), not written by hand.
  • Form.status and Form.owner_type are typed as Literal[...], matching the Pydantic schemas.
  • No migration: the schema is unchanged, and alembic check reports no new operations.

Logic

  • tournament_counts returns a TournamentCounts TypedDict, so the tournament list routes type-check.
  • Settings uses SettingsConfigDict, the documented config type for pydantic-settings.

Out of scope

  • Making always-set nullable columns NOT NULL (created_at, Form.tournament_id and others); about 40 of the remaining type errors depend on it, and it needs a migration.
  • The remaining 150 Pyright errors and adding type checking to CI.

Test plan

  • pytest passes locally
  • Migration included for every model change (no schema change)
  • Clicked through the UI change in a browser (no UI change)

Automated

  • A snapshot of every table, column, constraint, index and relationship setting is identical before and after, apart from collection_class None -> list on list relationships.
  • All 56 list relationships create the same InstrumentedList before and after, so that difference has no runtime effect.
  • alembic check against the dev database reports no new upgrade operations.
  • Ran core, auth, tournament core and admin, assignments, chapter, users, events and forms tests: all pass.
  • Pyright (basic mode) errors drop from 899 to 150; none involve Column types.

Manual

  • Checked the snapshot comparison catches the two risky conversion mistakes (a nullable column made NOT NULL, a list relationship made single) by introducing both on purpose.

@railway-app

railway-app Bot commented Oct 13, 2026

Copy link
Copy Markdown

This PR was not deployed automatically as @klin2686 does not have access to the Railway project.

In order to get automatic PR deploys, please add @klin2686 to your workspace on Railway.

@vercel

vercel Bot commented Oct 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
nexus Ready Ready Preview Oct 13, 2026 10:36am UTC

@klin2686
klin2686 merged commit fe6956d into main Oct 13, 2026
3 checks passed

This branch was successfully deployed

1 active deployment
Preview — ff06ef22 Deployed Oct 13, 2026 by vercel[bot]
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