test_server_defaults.py
python
sha256:ef10830ce231e0a20efcb0e2586cb879471247e916616e6fdd0d51df459e2595
fix: typing audit — 0 violations, 0 untyped defs across all…
Sonnet 4.6
minor
⚠ breaking
21 days ago
| 1 | """All non-nullable columns with a Python-side default must also have a |
| 2 | server_default so that raw SQL inserts (migrations, scripts, bulk loads) |
| 3 | produce a valid row without specifying the value. |
| 4 | |
| 5 | This covers the two most impactful categories: |
| 6 | - Booleans — always has a well-defined safe value (true / false) |
| 7 | - String enums / sentinel strings — open, pending, public, human, etc. |
| 8 | """ |
| 9 | from __future__ import annotations |
| 10 | |
| 11 | import typing |
| 12 | |
| 13 | import pytest |
| 14 | from sqlalchemy.orm import DeclarativeBase |
| 15 | |
| 16 | from musehub.db.coord_models import MusehubCoordTask |
| 17 | from musehub.db.musehub_collaborator_models import MusehubCollaborator |
| 18 | from musehub.db.musehub_domain_models import MusehubDomain |
| 19 | from musehub.db.musehub_identity_models import MusehubIdentity, MusehubProfileSnapshot |
| 20 | from musehub.db.musehub_intel_models import MusehubIntelApiSurface, MusehubIntelBreakageIssue, MusehubIntelClones, MusehubIntelEntangle, MusehubIntelResult, MusehubIntelStable, MusehubIntelType |
| 21 | from musehub.db.musehub_jobs_models import MusehubBackgroundJob |
| 22 | from musehub.db.musehub_release_models import MusehubRelease |
| 23 | from musehub.db.musehub_repo_models import MusehubBridgeMirror, MusehubMist, MusehubRepo, MusehubSession |
| 24 | from musehub.db.musehub_social_models import MusehubIssue, MusehubIssueComment, MusehubProposal, MusehubProposalReview |
| 25 | from musehub.db.musehub_webhook_models import MusehubWebhook, MusehubWebhookDelivery |
| 26 | |
| 27 | |
| 28 | def _server_default(model: type[DeclarativeBase], col_name: str) -> typing.Any: |
| 29 | return model.__table__.columns[col_name].server_default |
| 30 | |
| 31 | |
| 32 | def _assert_has_server_default(model: type[DeclarativeBase], col_name: str) -> None: |
| 33 | sd = _server_default(model, col_name) |
| 34 | assert sd is not None, ( |
| 35 | f"{model.__name__}.{col_name} has no server_default — " |
| 36 | "raw SQL inserts will fail or produce NULL" |
| 37 | ) |
| 38 | |
| 39 | |
| 40 | # --------------------------------------------------------------------------- |
| 41 | # Booleans |
| 42 | # --------------------------------------------------------------------------- |
| 43 | |
| 44 | BOOL_COLS = [ |
| 45 | (MusehubRepo, "training_opt_out"), |
| 46 | (MusehubIdentity, "is_verified"), |
| 47 | (MusehubIssueComment, "is_deleted"), |
| 48 | (MusehubRelease, "is_draft"), |
| 49 | (MusehubWebhook, "active"), |
| 50 | (MusehubWebhookDelivery, "success"), |
| 51 | (MusehubSession, "is_active"), |
| 52 | (MusehubIntelEntangle, "structurally_linked"), |
| 53 | (MusehubIntelStable, "since_start"), |
| 54 | (MusehubIntelType, "return_is_any"), |
| 55 | (MusehubBridgeMirror, "auto_export"), |
| 56 | (MusehubProfileSnapshot, "is_stale"), |
| 57 | (MusehubDomain, "is_verified"), |
| 58 | (MusehubDomain, "is_deprecated"), |
| 59 | ] |
| 60 | |
| 61 | |
| 62 | @pytest.mark.parametrize("model,col", BOOL_COLS, ids=[f"{m.__name__}.{c}" for m, c in BOOL_COLS]) |
| 63 | def test_bool_has_server_default(model: type[DeclarativeBase], col: str) -> None: |
| 64 | _assert_has_server_default(model, col) |
| 65 | |
| 66 | |
| 67 | # --------------------------------------------------------------------------- |
| 68 | # String enums / sentinel strings |
| 69 | # --------------------------------------------------------------------------- |
| 70 | |
| 71 | STR_ENUM_COLS = [ |
| 72 | (MusehubRepo, "visibility"), |
| 73 | (MusehubIdentity, "identity_type"), |
| 74 | (MusehubIssue, "state"), |
| 75 | (MusehubProposal, "state"), |
| 76 | (MusehubProposalReview, "state"), |
| 77 | (MusehubRelease, "channel"), |
| 78 | (MusehubSession, "schema_version"), |
| 79 | (MusehubBackgroundJob, "status"), |
| 80 | (MusehubIntelApiSurface, "visibility"), |
| 81 | (MusehubMist, "visibility"), |
| 82 | (MusehubIntelBreakageIssue, "severity"), |
| 83 | (MusehubBridgeMirror, "git_branch"), |
| 84 | (MusehubCollaborator, "permission"), |
| 85 | (MusehubCoordTask, "queue"), |
| 86 | (MusehubCoordTask, "status"), |
| 87 | (MusehubDomain, "version"), |
| 88 | (MusehubDomain, "viewer_type"), |
| 89 | ] |
| 90 | |
| 91 | |
| 92 | @pytest.mark.parametrize("model,col", STR_ENUM_COLS, ids=[f"{m.__name__}.{c}" for m, c in STR_ENUM_COLS]) |
| 93 | def test_str_enum_has_server_default(model: type[DeclarativeBase], col: str) -> None: |
| 94 | _assert_has_server_default(model, col) |
File History
1 commit
sha256:ef10830ce231e0a20efcb0e2586cb879471247e916616e6fdd0d51df459e2595
fix: typing audit — 0 violations, 0 untyped defs across all…
Sonnet 4.6
minor
⚠
21 days ago