Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions backend/druks/alembic_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ def _render_item(type_, obj, autogen_context):
return "sa.String()"
if type_ == "type" and isinstance(obj, EncryptedBytes | EncryptedJson | EncryptedText):
return "sa.LargeBinary()"
# The column's type emits its own CHECK. SQLAlchemy 2.1 hides that from Alembic's
# own detection, so without this skip the revision renders the CHECK twice more.
if type_ == "check" and obj._type_bound:
return None
return False


Expand Down
24 changes: 24 additions & 0 deletions backend/tests/test_app_migrations.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import enum
from pathlib import Path
from typing import Literal
from unittest.mock import MagicMock

from alembic import command
from alembic.autogenerate import render_python_code
from alembic.config import Config
from alembic.operations import ops
from druks.alembic_support import _render_item
from druks.database import make_app_migration
from druks.files import File, FileField
from druks.models import Base
Expand All @@ -24,6 +29,19 @@ class MigrationProbeFile(Base):
image: Mapped[File] = FileField()


class ChoiceProbeStatus(enum.StrEnum):
OPEN = "open"
CLOSED = "closed"


class ChoiceProbe(Base):
__tablename__ = "choice_probe_rows"

id: Mapped[int] = mapped_column(Integer, primary_key=True)
status: Mapped[ChoiceProbeStatus]
tone: Mapped[Literal["calm", "loud"]]


_BASELINE = """\
import sqlalchemy as sa
from alembic import op
Expand Down Expand Up @@ -185,3 +203,9 @@ def test_file_field_autogenerates_and_upgrades_with_the_platform_foreign_key(
"DROP TABLE IF EXISTS migration_probe_files, alembic_version_migration_probe"
)
engine.dispose()


def test_choice_columns_render_no_check_beside_their_type():
"""A StrEnum or Literal column's type emits its own CHECK."""
upgrade = ops.UpgradeOps([ops.CreateTableOp.from_table(ChoiceProbe.__table__)])
assert "CheckConstraint" not in render_python_code(upgrade, render_item=_render_item)
Loading