Skip to content

Make chat_type a native enum and test migrations with pytest-alembic - #4

Merged
lesnik512 merged 3 commits into
mainfrom
enum-native-and-migration-tests
Aug 21, 2026
Merged

Make chat_type a native enum and test migrations with pytest-alembic#4
lesnik512 merged 3 commits into
mainfrom
enum-native-and-migration-tests

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Supersedes #3, which GitHub auto-closed when its stacked base branch was deleted
on merge of #2. Same branch, rebased onto main.

Rationale in
planning/changes/2026-08-21.03-native-enum-and-migration-tests.md.

Native enum

sa.Enum(native_enum=False, create_constraint=True) produced a permanent
autogenerate false positive — Postgres reflects the CHECK body as
chat_type::text = ANY (ARRAY[...]), which never matches what Alembic renders
from the model, so every run proposed dropping ck_chats_chattype. alembic check could therefore never be a drift gate.

chat_type is now a native Postgres enum and migrations/env.py imports
alembic-postgresql-enum for its autogenerate hooks. The library wrote the
entire conversion migration, USING clause and working downgrade included.

Migration tests

tests/migrations/ runs four pytest-alembic built-ins:
test_single_head_revision, test_upgrade, test_up_down_consistency and
test_model_definitions_match_ddl (the last is alembic check as a test).
just test only ever ran downgrade base && upgrade head, which proves neither
per-revision reversibility nor the absence of branched heads.

The suite cycles the schema out from under db_session's rollback fixture, so
it is excluded from the default run (--ignore in addopts, omit in
coverage) and gets just test-migrations plus its own CI step.

Also

  • Settings.sync_db_dsn_parsed owns the asyncpgpsycopg2 DSN rewrite that
    env.py and the alembic_engine fixture both need.
  • alembic.ini gains path_separator = os; without it Alembic's
    DeprecationWarning fails tests under filterwarnings = ["error"].
  • Second commit: pylint.max-args = 10 in the ruff config replaces eight
    # noqa: PLR0913, PLR0917 annotations. Litestar binds path/query/DI params by
    name and pytest binds fixtures by name, so handlers and tests legitimately
    exceed the default of five. max-positional-args defaults to max-args, so
    one setting covers both rules.

Verification

  • just test — 109 passed, 100% coverage.
  • just test-migrations — 4 passed.
  • just lint, just check-planning — clean.
  • alembic upgrade head && alembic check — clean (previously reported
    remove_constraint ck_chats_chattype); downgrade -1 && upgrade head
    round-trips.

sa.Enum(native_enum=False, create_constraint=True) produced a permanent
autogenerate false positive: Postgres reflects the CHECK body as
chat_type::text = ANY (ARRAY[...]), which never matches what Alembic renders
from the model, so every run proposed dropping ck_chats_chattype. That kept
alembic check from ever being usable as a drift gate.

chat_type is now a native Postgres enum and migrations/env.py imports
alembic-postgresql-enum for its autogenerate hooks - which wrote the whole
conversion, USING clause and working downgrade included.

tests/migrations/ runs the four pytest-alembic built-ins, including
test_model_definitions_match_ddl (alembic check as a test) and
test_up_down_consistency, which just test never covered. The suite cycles the
schema, so it is excluded from the default run and from coverage, and gets
its own just recipe and CI step.

Settings.sync_db_dsn_parsed now owns the asyncpg -> psycopg2 DSN rewrite that
env.py and the alembic_engine fixture both need. alembic.ini gains
path_separator = os so Alembic's deprecation warning stops failing tests under
filterwarnings = ["error"].
Litestar binds path/query/DI params by name and pytest binds fixtures by
name, so handlers and tests legitimately take more than five parameters.
Eight # noqa: PLR0913, PLR0917 annotations existed only to say that.
max-positional-args defaults to max-args, so one setting covers both rules.
The migration tests were appended to the pytest job, so a failing app suite
meant they never ran at all and a red job did not say which half broke. They
also ran against a database the app suite had left at head, rewound by an
`alembic downgrade base` step - implicit setup doing work that
test_up_down_consistency already covers.

A matrix over the two commands gives each an independent signal and a fresh
database, while keeping one services block and one setup stanza. fail-fast is
off so one leg's failure does not cancel the other.

The same downgrade was redundant in `just test-migrations`: the compose db
service has no volume, so the recipe's leading `down` already yields an empty
database.
@lesnik512
lesnik512 merged commit 8af9bcc into main Aug 21, 2026
3 checks passed
@lesnik512
lesnik512 deleted the enum-native-and-migration-tests branch August 21, 2026 19:10
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