-
Notifications
You must be signed in to change notification settings - Fork 4
BDMS-576: Add transfer accountability tooling, duplicate WellData comparison, transfer hardening/perf, and nullable schema updates #537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1195f1a
e8d8bf3
cfb576e
2d4d8ff
ba7881b
b4764b2
3528718
fd7e243
41ff8de
a2baff6
d2f4f1f
e089b32
c9cf672
7824779
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,6 +45,7 @@ transfers/logs/* | |
| run_bdd-local.sh | ||
| .pre-commit-config.local.yaml | ||
| .serena/ | ||
| cli/logs | ||
|
|
||
| # deployment files | ||
| app.yaml | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| """make measuring_point_history.measuring_point_height nullable | ||
|
|
||
| Revision ID: 8c9d0e1f2a3b | ||
| Revises: 5336a52336df | ||
| Create Date: 2026-02-21 12:00:00.000000 | ||
|
|
||
| """ | ||
|
|
||
| from typing import Sequence, Union | ||
|
|
||
| import sqlalchemy as sa | ||
| from alembic import op | ||
|
|
||
| # revision identifiers, used by Alembic. | ||
| revision: str = "8c9d0e1f2a3b" | ||
| down_revision: Union[str, Sequence[str], None] = "5336a52336df" | ||
| branch_labels: Union[str, Sequence[str], None] = None | ||
| depends_on: Union[str, Sequence[str], None] = None | ||
|
|
||
|
|
||
| def upgrade() -> None: | ||
| op.alter_column( | ||
| "measuring_point_history", | ||
| "measuring_point_height", | ||
| existing_type=sa.Numeric(), | ||
| nullable=True, | ||
| ) | ||
|
|
||
|
|
||
| def downgrade() -> None: | ||
| op.alter_column( | ||
| "measuring_point_history", | ||
| "measuring_point_height", | ||
| existing_type=sa.Numeric(), | ||
| nullable=False, | ||
| ) | ||
|
Comment on lines
+30
to
+36
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| """make address.postal_code nullable | ||
|
|
||
| Revision ID: 9a0b1c2d3e4f | ||
| Revises: 8c9d0e1f2a3b | ||
| Create Date: 2026-02-21 13:00:00.000000 | ||
|
|
||
| """ | ||
|
|
||
| from typing import Sequence, Union | ||
|
|
||
| import sqlalchemy as sa | ||
| from alembic import op | ||
|
|
||
| # revision identifiers, used by Alembic. | ||
| revision: str = "9a0b1c2d3e4f" | ||
| down_revision: Union[str, Sequence[str], None] = "8c9d0e1f2a3b" | ||
| branch_labels: Union[str, Sequence[str], None] = None | ||
| depends_on: Union[str, Sequence[str], None] = None | ||
|
|
||
|
|
||
| def upgrade() -> None: | ||
| op.alter_column( | ||
| "address", | ||
| "postal_code", | ||
| existing_type=sa.String(length=20), | ||
| nullable=True, | ||
| ) | ||
|
|
||
|
|
||
| def downgrade() -> None: | ||
| op.alter_column( | ||
| "address", | ||
| "postal_code", | ||
| existing_type=sa.String(length=20), | ||
| nullable=False, | ||
| ) | ||
jirhiker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| """make deployment installation_date nullable | ||
|
|
||
| Revision ID: a1b2c3d4e5f7 | ||
| Revises: 9a0b1c2d3e4f | ||
| Create Date: 2026-02-21 14:32:00.000000 | ||
|
|
||
| """ | ||
|
|
||
| from typing import Sequence, Union | ||
|
|
||
| import sqlalchemy as sa | ||
| from alembic import op | ||
|
|
||
| # revision identifiers, used by Alembic. | ||
| revision: str = "a1b2c3d4e5f7" | ||
| down_revision: Union[str, Sequence[str], None] = "9a0b1c2d3e4f" | ||
| branch_labels: Union[str, Sequence[str], None] = None | ||
| depends_on: Union[str, Sequence[str], None] = None | ||
|
|
||
|
|
||
| def upgrade() -> None: | ||
| op.alter_column( | ||
| "deployment", | ||
| "installation_date", | ||
| existing_type=sa.Date(), | ||
| nullable=True, | ||
| ) | ||
|
|
||
|
|
||
| def downgrade() -> None: | ||
| op.alter_column( | ||
| "deployment", | ||
| "installation_date", | ||
| existing_type=sa.Date(), | ||
| nullable=False, | ||
| ) | ||
jirhiker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,48 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| """make wellscreen depth fields nullable | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| Revision ID: b3c4d5e6f7a8 | ||||||||||||||||||||||||||||||||||||||||||||||
| Revises: a1b2c3d4e5f7 | ||||||||||||||||||||||||||||||||||||||||||||||
| Create Date: 2026-02-21 15:20:00.000000 | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| from typing import Sequence, Union | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| import sqlalchemy as sa | ||||||||||||||||||||||||||||||||||||||||||||||
| from alembic import op | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| # revision identifiers, used by Alembic. | ||||||||||||||||||||||||||||||||||||||||||||||
| revision: str = "b3c4d5e6f7a8" | ||||||||||||||||||||||||||||||||||||||||||||||
| down_revision: Union[str, Sequence[str], None] = "a1b2c3d4e5f7" | ||||||||||||||||||||||||||||||||||||||||||||||
| branch_labels: Union[str, Sequence[str], None] = None | ||||||||||||||||||||||||||||||||||||||||||||||
| depends_on: Union[str, Sequence[str], None] = None | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| def upgrade() -> None: | ||||||||||||||||||||||||||||||||||||||||||||||
| op.alter_column( | ||||||||||||||||||||||||||||||||||||||||||||||
| "well_screen", | ||||||||||||||||||||||||||||||||||||||||||||||
| "screen_depth_top", | ||||||||||||||||||||||||||||||||||||||||||||||
| existing_type=sa.Float(), | ||||||||||||||||||||||||||||||||||||||||||||||
| nullable=True, | ||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||
| op.alter_column( | ||||||||||||||||||||||||||||||||||||||||||||||
| "well_screen", | ||||||||||||||||||||||||||||||||||||||||||||||
| "screen_depth_bottom", | ||||||||||||||||||||||||||||||||||||||||||||||
| existing_type=sa.Float(), | ||||||||||||||||||||||||||||||||||||||||||||||
| nullable=True, | ||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| def downgrade() -> None: | ||||||||||||||||||||||||||||||||||||||||||||||
| op.alter_column( | ||||||||||||||||||||||||||||||||||||||||||||||
| "well_screen", | ||||||||||||||||||||||||||||||||||||||||||||||
| "screen_depth_bottom", | ||||||||||||||||||||||||||||||||||||||||||||||
| existing_type=sa.Float(), | ||||||||||||||||||||||||||||||||||||||||||||||
| nullable=False, | ||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||
| op.alter_column( | ||||||||||||||||||||||||||||||||||||||||||||||
| "well_screen", | ||||||||||||||||||||||||||||||||||||||||||||||
| "screen_depth_top", | ||||||||||||||||||||||||||||||||||||||||||||||
| existing_type=sa.Float(), | ||||||||||||||||||||||||||||||||||||||||||||||
| nullable=False, | ||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+37
to
+48
|
||||||||||||||||||||||||||||||||||||||||||||||
| op.alter_column( | |
| "well_screen", | |
| "screen_depth_bottom", | |
| existing_type=sa.Float(), | |
| nullable=False, | |
| ) | |
| op.alter_column( | |
| "well_screen", | |
| "screen_depth_top", | |
| existing_type=sa.Float(), | |
| nullable=False, | |
| ) | |
| # Downgrading this migration is unsafe once NULL values may exist in | |
| # well_screen.screen_depth_top or well_screen.screen_depth_bottom. | |
| # Changing these columns back to NOT NULL could fail or require | |
| # destructive data changes. To avoid silent data corruption or | |
| # database errors, this downgrade is intentionally disabled. | |
| raise RuntimeError( | |
| "Downgrade of migration b3c4d5e6f7a8 is unsupported because " | |
| "well_screen.screen_depth_top and well_screen.screen_depth_bottom " | |
| "may contain NULL values after the upgrade." | |
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| """make address.city and address.state nullable | ||
|
|
||
| Revision ID: c4d5e6f7a8b9 | ||
| Revises: b3c4d5e6f7a8 | ||
| Create Date: 2026-02-21 16:30:00.000000 | ||
|
|
||
| """ | ||
|
|
||
| from typing import Sequence, Union | ||
|
|
||
| import sqlalchemy as sa | ||
| from alembic import op | ||
|
|
||
| # revision identifiers, used by Alembic. | ||
| revision: str = "c4d5e6f7a8b9" | ||
| down_revision: Union[str, Sequence[str], None] = "b3c4d5e6f7a8" | ||
| branch_labels: Union[str, Sequence[str], None] = None | ||
| depends_on: Union[str, Sequence[str], None] = None | ||
|
|
||
|
|
||
| def upgrade() -> None: | ||
| op.alter_column( | ||
| "address", | ||
| "city", | ||
| existing_type=sa.String(length=100), | ||
| nullable=True, | ||
| ) | ||
| op.alter_column( | ||
| "address", | ||
| "state", | ||
| existing_type=sa.String(length=50), | ||
| nullable=True, | ||
| ) | ||
|
|
||
|
|
||
| def downgrade() -> None: | ||
| op.alter_column( | ||
| "address", | ||
| "city", | ||
| existing_type=sa.String(length=100), | ||
| nullable=False, | ||
| ) | ||
| op.alter_column( | ||
| "address", | ||
| "state", | ||
| existing_type=sa.String(length=50), | ||
| nullable=False, | ||
| ) | ||
jirhiker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # API | ||
|
|
||
| This directory contains FastAPI route modules grouped by resource/domain. | ||
|
|
||
| ## Structure | ||
|
|
||
| - One module per domain (for example `thing.py`, `contact.py`, `observation.py`) | ||
| - `api/ogc/` contains OGC-specific endpoints | ||
|
|
||
| ## Guidelines | ||
|
|
||
| - Keep endpoints focused on transport concerns (request/response, status codes). | ||
| - Put transfer/business logic in service or transfer modules. | ||
| - Ensure response schemas match `schemas/` definitions. | ||
|
|
||
| ## Running locally | ||
|
|
||
| Use project entrypoint from repo root (see top-level README for full setup). |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # CLI | ||
|
|
||
| This directory contains Typer-based command entrypoints for operational and migration workflows. | ||
|
|
||
| ## Main entrypoint | ||
|
|
||
| - `cli/cli.py` | ||
|
|
||
| Run commands from repo root: | ||
|
|
||
| ```bash | ||
| source .venv/bin/activate | ||
| python -m cli.cli --help | ||
| ``` | ||
|
|
||
| ## Common commands | ||
|
|
||
| - `python -m cli.cli transfer-results` | ||
| - `python -m cli.cli compare-duplicated-welldata` | ||
| - `python -m cli.cli alembic-upgrade-and-data` | ||
|
|
||
| ## Notes | ||
|
|
||
| - CLI logging is written to `cli/logs/`. | ||
| - Keep CLI commands thin; move heavy logic into service/transfer modules. |
Uh oh!
There was an error while loading. Please reload this page.