mainsequence-metatable 0.1.4.dev5__py3-none-any.whl → 0.1.5.dev6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- api/app/configuration.py +1 -2
- api/app/main.py +0 -2
- api/app/routes/managed_finalize.py +1 -1
- api/app/routes/migration_connection.py +71 -19
- api/app/routes/run_logs.py +34 -1
- api/app/routes/runtime_context.py +0 -1
- api/app/routes/update_crud.py +7 -3
- api/backend/backends/catalog.py +0 -24
- api/backend/backends/contracts.py +0 -2
- api/backend/backends/hosted.py +0 -13
- api/backend/backends/migration_connection.py +62 -0
- api/backend/integrations/run_logs.py +3 -3
- api/backend/persistence/run_graphs.py +15 -4
- api/metatables/configuration.yaml +0 -2
- examples/README.md +1 -1
- examples/local_app/README.md +5 -7
- examples/local_app/migrations/__init__.py +1 -1
- examples/scripts/setup_metatables.py +2 -12
- examples/tutorial/README.md +67 -20
- examples/tutorial/__main__.py +12 -6
- examples/tutorial/frames.py +32 -1
- examples/tutorial/migrations/registry.py +5 -3
- examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +42 -0
- examples/tutorial/operations.py +9 -1
- examples/tutorial/tables.py +37 -1
- examples/tutorial/updaters.py +86 -9
- {mainsequence_metatable-0.1.4.dev5.dist-info → mainsequence_metatable-0.1.5.dev6.dist-info}/METADATA +1 -1
- {mainsequence_metatable-0.1.4.dev5.dist-info → mainsequence_metatable-0.1.5.dev6.dist-info}/RECORD +279 -188
- metatables/_client_skills/metatables-local-development/SKILL.md +7 -8
- metatables/_client_skills/metatables-local-development/references/docs/adr/api/0001-unified-api-storage-and-local-sqlite.md +9 -2
- metatables/_client_skills/metatables-local-development/references/docs/adr/api/0002-application-administration-and-table-ownership.md +11 -3
- metatables/_client_skills/metatables-local-development/references/docs/adr/api/0004-approved-application-migrations.md +10 -1
- metatables/_client_skills/metatables-local-development/references/docs/adr/api/0007-database-enforced-table-access.md +14 -0
- metatables/_client_skills/metatables-local-development/references/docs/adr/api/0008-mysql-mssql-table-workflows.md +7 -0
- metatables/_client_skills/metatables-local-development/references/docs/adr/api/0009-shared-credential-store.md +7 -0
- metatables/_client_skills/metatables-local-development/references/docs/adr/api/0013-application-owned-migrations.md +113 -0
- metatables/_client_skills/metatables-local-development/references/docs/adr/client/0011-cli-local-development-with-managed-admin.md +19 -16
- metatables/_client_skills/metatables-local-development/references/docs/adr/index.md +3 -2
- metatables/_client_skills/metatables-local-development/references/docs/api/openapi.json +164 -63
- metatables/_client_skills/metatables-local-development/references/docs/api/reference.md +1 -1
- metatables/_client_skills/metatables-local-development/references/docs/api/time-index-and-updates.md +11 -4
- metatables/_client_skills/metatables-local-development/references/docs/client/define-and-migrate-tables.md +39 -25
- metatables/_client_skills/metatables-local-development/references/docs/client/installation-and-connection.md +12 -6
- metatables/_client_skills/metatables-local-development/references/docs/client/query-and-mutate.md +4 -0
- metatables/_client_skills/metatables-local-development/references/docs/client/tutorial.md +86 -36
- metatables/_client_skills/metatables-local-development/references/docs/client/upgrade-legacy-app.md +157 -0
- metatables/_client_skills/metatables-local-development/references/docs/concepts/architecture.md +6 -4
- metatables/_client_skills/metatables-local-development/references/docs/concepts/runs-and-execution-graphs.md +37 -18
- metatables/_client_skills/metatables-local-development/references/docs/contributing/releasing.md +3 -3
- metatables/_client_skills/metatables-local-development/references/docs/examples/README.md +1 -1
- metatables/_client_skills/metatables-local-development/references/docs/examples/local_app/README.md +5 -7
- metatables/_client_skills/metatables-local-development/references/docs/examples/local_app/migrations/__init__.py +1 -1
- metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/README.md +67 -20
- metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/frames.py +32 -1
- metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/migrations/registry.py +5 -3
- metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +42 -0
- metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/operations.py +9 -1
- metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/tables.py +37 -1
- metatables/_client_skills/metatables-local-development/references/docs/examples/tutorial/updaters.py +86 -9
- metatables/_client_skills/metatables-local-development/references/docs/operations/catalog-migrations.md +2 -2
- metatables/_client_skills/metatables-local-development/references/docs/operations/configuration.md +6 -12
- metatables/_client_skills/metatables-local-development/references/docs/operations/local-runtime.md +4 -3
- metatables/_client_skills/metatables-local-development/references/docs/operations/run-history.md +30 -17
- metatables/_client_skills/metatables-local-development/references/docs/operations/run-logs.md +4 -1
- metatables/_client_skills/metatables-local-development/references/docs/reference/capabilities.md +8 -8
- metatables/_client_skills/metatables-local-development/references/docs/security/index.md +15 -13
- metatables/_client_skills/metatables-local-development/references/docs/security/permissions.md +8 -6
- metatables/_client_skills/metatables-local-development/references/examples/local_app/README.md +5 -7
- metatables/_client_skills/metatables-local-development/references/examples/local_app/migrations/__init__.py +1 -1
- metatables/_client_skills/metatables-meta-tables/SKILL.md +20 -5
- metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0001-unified-api-storage-and-local-sqlite.md +9 -2
- metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0002-application-administration-and-table-ownership.md +11 -3
- metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0004-approved-application-migrations.md +10 -1
- metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0007-database-enforced-table-access.md +14 -0
- metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0008-mysql-mssql-table-workflows.md +7 -0
- metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0009-shared-credential-store.md +7 -0
- metatables/_client_skills/metatables-meta-tables/references/docs/adr/api/0013-application-owned-migrations.md +113 -0
- metatables/_client_skills/metatables-meta-tables/references/docs/adr/client/0011-cli-local-development-with-managed-admin.md +19 -16
- metatables/_client_skills/metatables-meta-tables/references/docs/adr/index.md +3 -2
- metatables/_client_skills/metatables-meta-tables/references/docs/api/openapi.json +164 -63
- metatables/_client_skills/metatables-meta-tables/references/docs/api/reference.md +1 -1
- metatables/_client_skills/metatables-meta-tables/references/docs/api/time-index-and-updates.md +11 -4
- metatables/_client_skills/metatables-meta-tables/references/docs/client/define-and-migrate-tables.md +39 -25
- metatables/_client_skills/metatables-meta-tables/references/docs/client/installation-and-connection.md +12 -6
- metatables/_client_skills/metatables-meta-tables/references/docs/client/query-and-mutate.md +4 -0
- metatables/_client_skills/metatables-meta-tables/references/docs/client/tutorial.md +86 -36
- metatables/_client_skills/metatables-meta-tables/references/docs/client/upgrade-legacy-app.md +157 -0
- metatables/_client_skills/metatables-meta-tables/references/docs/concepts/architecture.md +6 -4
- metatables/_client_skills/metatables-meta-tables/references/docs/concepts/runs-and-execution-graphs.md +37 -18
- metatables/_client_skills/metatables-meta-tables/references/docs/contributing/releasing.md +3 -3
- metatables/_client_skills/metatables-meta-tables/references/docs/examples/README.md +1 -1
- metatables/_client_skills/metatables-meta-tables/references/docs/examples/local_app/README.md +5 -7
- metatables/_client_skills/metatables-meta-tables/references/docs/examples/local_app/migrations/__init__.py +1 -1
- metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/README.md +67 -20
- metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/frames.py +32 -1
- metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/migrations/registry.py +5 -3
- metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +42 -0
- metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/operations.py +9 -1
- metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/tables.py +37 -1
- metatables/_client_skills/metatables-meta-tables/references/docs/examples/tutorial/updaters.py +86 -9
- metatables/_client_skills/metatables-meta-tables/references/docs/operations/catalog-migrations.md +2 -2
- metatables/_client_skills/metatables-meta-tables/references/docs/operations/configuration.md +6 -12
- metatables/_client_skills/metatables-meta-tables/references/docs/operations/local-runtime.md +4 -3
- metatables/_client_skills/metatables-meta-tables/references/docs/operations/run-history.md +30 -17
- metatables/_client_skills/metatables-meta-tables/references/docs/operations/run-logs.md +4 -1
- metatables/_client_skills/metatables-meta-tables/references/docs/reference/capabilities.md +8 -8
- metatables/_client_skills/metatables-meta-tables/references/docs/security/index.md +15 -13
- metatables/_client_skills/metatables-meta-tables/references/docs/security/permissions.md +8 -6
- metatables/_client_skills/metatables-migrations/SKILL.md +36 -32
- metatables/_client_skills/metatables-migrations/references/docs/adr/api/0001-unified-api-storage-and-local-sqlite.md +9 -2
- metatables/_client_skills/metatables-migrations/references/docs/adr/api/0002-application-administration-and-table-ownership.md +11 -3
- metatables/_client_skills/metatables-migrations/references/docs/adr/api/0004-approved-application-migrations.md +10 -1
- metatables/_client_skills/metatables-migrations/references/docs/adr/api/0007-database-enforced-table-access.md +14 -0
- metatables/_client_skills/metatables-migrations/references/docs/adr/api/0008-mysql-mssql-table-workflows.md +7 -0
- metatables/_client_skills/metatables-migrations/references/docs/adr/api/0009-shared-credential-store.md +7 -0
- metatables/_client_skills/metatables-migrations/references/docs/adr/api/0013-application-owned-migrations.md +113 -0
- metatables/_client_skills/metatables-migrations/references/docs/adr/client/0011-cli-local-development-with-managed-admin.md +19 -16
- metatables/_client_skills/metatables-migrations/references/docs/adr/index.md +3 -2
- metatables/_client_skills/metatables-migrations/references/docs/api/openapi.json +164 -63
- metatables/_client_skills/metatables-migrations/references/docs/api/reference.md +1 -1
- metatables/_client_skills/metatables-migrations/references/docs/api/time-index-and-updates.md +11 -4
- metatables/_client_skills/metatables-migrations/references/docs/client/define-and-migrate-tables.md +39 -25
- metatables/_client_skills/metatables-migrations/references/docs/client/installation-and-connection.md +12 -6
- metatables/_client_skills/metatables-migrations/references/docs/client/query-and-mutate.md +4 -0
- metatables/_client_skills/metatables-migrations/references/docs/client/tutorial.md +86 -36
- metatables/_client_skills/metatables-migrations/references/docs/client/upgrade-legacy-app.md +157 -0
- metatables/_client_skills/metatables-migrations/references/docs/concepts/architecture.md +6 -4
- metatables/_client_skills/metatables-migrations/references/docs/concepts/runs-and-execution-graphs.md +37 -18
- metatables/_client_skills/metatables-migrations/references/docs/contributing/releasing.md +3 -3
- metatables/_client_skills/metatables-migrations/references/docs/examples/README.md +1 -1
- metatables/_client_skills/metatables-migrations/references/docs/examples/local_app/README.md +5 -7
- metatables/_client_skills/metatables-migrations/references/docs/examples/local_app/migrations/__init__.py +1 -1
- metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/README.md +67 -20
- metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/frames.py +32 -1
- metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/migrations/registry.py +5 -3
- metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +42 -0
- metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/operations.py +9 -1
- metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/tables.py +37 -1
- metatables/_client_skills/metatables-migrations/references/docs/examples/tutorial/updaters.py +86 -9
- metatables/_client_skills/metatables-migrations/references/docs/operations/catalog-migrations.md +2 -2
- metatables/_client_skills/metatables-migrations/references/docs/operations/configuration.md +6 -12
- metatables/_client_skills/metatables-migrations/references/docs/operations/local-runtime.md +4 -3
- metatables/_client_skills/metatables-migrations/references/docs/operations/run-history.md +30 -17
- metatables/_client_skills/metatables-migrations/references/docs/operations/run-logs.md +4 -1
- metatables/_client_skills/metatables-migrations/references/docs/reference/capabilities.md +8 -8
- metatables/_client_skills/metatables-migrations/references/docs/security/index.md +15 -13
- metatables/_client_skills/metatables-migrations/references/docs/security/permissions.md +8 -6
- metatables/_client_skills/metatables-migrations/references/examples/scripts/setup_metatables.py +2 -12
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0001-unified-api-storage-and-local-sqlite.md +9 -2
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0002-application-administration-and-table-ownership.md +11 -3
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0004-approved-application-migrations.md +10 -1
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0007-database-enforced-table-access.md +14 -0
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0008-mysql-mssql-table-workflows.md +7 -0
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0009-shared-credential-store.md +7 -0
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/api/0013-application-owned-migrations.md +113 -0
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/client/0011-cli-local-development-with-managed-admin.md +19 -16
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/adr/index.md +3 -2
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/api/openapi.json +164 -63
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/api/reference.md +1 -1
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/api/time-index-and-updates.md +11 -4
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/client/define-and-migrate-tables.md +39 -25
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/client/installation-and-connection.md +12 -6
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/client/query-and-mutate.md +4 -0
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/client/tutorial.md +86 -36
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/client/upgrade-legacy-app.md +157 -0
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/concepts/architecture.md +6 -4
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/concepts/runs-and-execution-graphs.md +37 -18
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/contributing/releasing.md +3 -3
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/README.md +1 -1
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/local_app/README.md +5 -7
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/local_app/migrations/__init__.py +1 -1
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/README.md +67 -20
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/frames.py +32 -1
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/migrations/registry.py +5 -3
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +42 -0
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/operations.py +9 -1
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/tables.py +37 -1
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/examples/tutorial/updaters.py +86 -9
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/operations/catalog-migrations.md +2 -2
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/operations/configuration.md +6 -12
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/operations/local-runtime.md +4 -3
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/operations/run-history.md +30 -17
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/operations/run-logs.md +4 -1
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/reference/capabilities.md +8 -8
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/security/index.md +15 -13
- metatables/_client_skills/metatables-time-index-table-updates/references/docs/security/permissions.md +8 -6
- metatables/_client_skills/metatables-upgrade-legacy-app/SKILL.md +91 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0001-unified-api-storage-and-local-sqlite.md +656 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0002-application-administration-and-table-ownership.md +374 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0004-approved-application-migrations.md +66 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0005-run-logs-and-local-file-capture.md +237 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0006-historical-run-graphs.md +288 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0007-database-enforced-table-access.md +294 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0007-database-roles-and-privileges.svg +120 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0007-query-enforcement-path.svg +76 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0008-mysql-mssql-table-workflows.md +430 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0009-shared-credential-store.md +196 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0010-import-external-tables-and-views.md +605 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0012-bounded-data-transfer-and-safe-retries.md +428 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/api/0013-application-owned-migrations.md +113 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/client/0003-api-endpoint-resolution.md +236 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/client/0011-cli-local-development-with-managed-admin.md +301 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/adr/index.md +36 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/api/authentication-and-errors.md +75 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/api/data-sources.md +198 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/api/openapi.json +9853 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/api/reference.md +118 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/api/time-index-and-updates.md +110 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/assets/diagrams/local-client-experience.svg +91 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/bounded-transfers.md +153 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/build-an-updater.md +58 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/define-and-migrate-tables.md +102 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/installation-and-connection.md +177 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/query-and-mutate.md +86 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/read-existing-time-index-tables.md +36 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/tutorial.md +235 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/client/upgrade-legacy-app.md +157 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/concepts/architecture.md +92 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/concepts/data-sources.md +162 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/concepts/permissions-namespaces-labels.md +41 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/concepts/runs-and-execution-graphs.md +134 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/concepts/table-contracts-and-lifecycle.md +58 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/concepts/time-index-tables-and-updates.md +60 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/contributing/database-backends.md +82 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/contributing/documentation.md +76 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/contributing/releasing.md +155 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/contributing/testing.md +136 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/README.md +34 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/bounded_reader.py +12 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/data_sources/README.md +27 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/data_sources/mssql.json +16 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/data_sources/mysql.json +16 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/data_sources/postgresql.json +15 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/external_table.py +20 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/local_app/README.md +53 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/local_app/migrations/__init__.py +21 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/local_app/tables.py +20 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/query.py +19 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/quickstart.py +17 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/reader.py +12 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tables.py +49 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/README.md +129 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/data/README.md +13 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/data/yahoo_spy_qqq_iwm_2026-06-15_2026-07-17.csv +70 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/frames.py +79 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/migrations/__init__.py +29 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/migrations/registry.py +11 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0001_create_market_tutorial_tables.py +81 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/migrations/versions/metatables_market_tutorial/0002_create_rolling_volatility.py +42 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/operations.py +75 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/tables.py +150 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/tutorial/updaters.py +172 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/examples/updater.py +42 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/catalog-migrations.md +150 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/configuration.md +56 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/hosted-runtime.md +100 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/local-runtime.md +192 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/recovery-and-observability.md +66 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/run-history.md +144 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/operations/run-logs.md +131 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/reference/capabilities.md +307 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/security/index.md +174 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/security/ownership-and-sharing.md +145 -0
- metatables/_client_skills/metatables-upgrade-legacy-app/references/docs/security/permissions.md +107 -0
- metatables/cli/app.py +2 -3
- metatables/cli/migrations.py +51 -88
- metatables/cli/project.py +1 -11
- metatables/migrations/__init__.py +14 -3
- metatables/migrations/connection.py +75 -0
- metatables/migrations/env.py +7 -33
- metatables/migrations/runner.py +152 -0
- metatables/migrations/tls.py +25 -7
- metatables/models.py +7 -2
- metatables/runtime.py +6 -6
- metatables/runtime_contract.py +0 -1
- api/app/routes/application_migrations.py +0 -170
- metatables/_client_skills/metatables-migrations/references/docs/api/tables-and-migrations.md +0 -156
- metatables/_client_skills/metatables-migrations/references/docs/client/register-existing-tables.md +0 -109
- {mainsequence_metatable-0.1.4.dev5.dist-info → mainsequence_metatable-0.1.5.dev6.dist-info}/WHEEL +0 -0
- {mainsequence_metatable-0.1.4.dev5.dist-info → mainsequence_metatable-0.1.5.dev6.dist-info}/entry_points.txt +0 -0
- {mainsequence_metatable-0.1.4.dev5.dist-info → mainsequence_metatable-0.1.5.dev6.dist-info}/licenses/LICENSE +0 -0
- {mainsequence_metatable-0.1.4.dev5.dist-info → mainsequence_metatable-0.1.5.dev6.dist-info}/top_level.txt +0 -0
api/app/configuration.py
CHANGED
|
@@ -4,7 +4,7 @@ from pathlib import Path
|
|
|
4
4
|
from typing import Literal
|
|
5
5
|
|
|
6
6
|
import yaml
|
|
7
|
-
from pydantic import BaseModel, ConfigDict, Field, StrictBool
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, Field, StrictBool
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class LocalCredentialConfiguration(BaseModel):
|
|
@@ -16,7 +16,6 @@ class LocalCredentialConfiguration(BaseModel):
|
|
|
16
16
|
class DeploymentConfiguration(BaseModel):
|
|
17
17
|
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
18
18
|
local_mode_available: StrictBool = False
|
|
19
|
-
application_migration_providers: dict[StrictStr, StrictStr] = Field(default_factory=dict)
|
|
20
19
|
local_credentials: LocalCredentialConfiguration = Field(default_factory=LocalCredentialConfiguration)
|
|
21
20
|
|
|
22
21
|
@classmethod
|
api/app/main.py
CHANGED
|
@@ -10,7 +10,6 @@ from sqlalchemy.orm import Session
|
|
|
10
10
|
|
|
11
11
|
from api.app.auth.boundary import trusted_actor_facts
|
|
12
12
|
from api.app.auth.local_actor import catalog_session
|
|
13
|
-
from api.app.routes.application_migrations import router as application_migrations_router
|
|
14
13
|
from api.app.routes.column_search import router as column_search_router
|
|
15
14
|
from api.app.routes.contract_validation import router as contract_validation_router
|
|
16
15
|
from api.app.routes.data_sources import router as data_sources_router
|
|
@@ -189,7 +188,6 @@ def create_app(config: RuntimeConfig | None = None) -> FastAPI:
|
|
|
189
188
|
service.include_router(managed_finalize_router)
|
|
190
189
|
service.include_router(table_sql_router)
|
|
191
190
|
service.include_router(migration_connection_router)
|
|
192
|
-
service.include_router(application_migrations_router)
|
|
193
191
|
service.include_router(table_import_router)
|
|
194
192
|
service.include_router(source_relations_router)
|
|
195
193
|
service.include_router(table_registration_router)
|
|
@@ -203,7 +203,7 @@ def finalize_managed(
|
|
|
203
203
|
table.introspection_snapshot = snapshot
|
|
204
204
|
table.provisioning_status = "active"
|
|
205
205
|
table.protect_from_deletion = True
|
|
206
|
-
if payload.
|
|
206
|
+
if "alembic_revision" in payload.model_fields_set:
|
|
207
207
|
table.alembic_revision = payload.alembic_revision
|
|
208
208
|
if version_root is not None and uid != version_root:
|
|
209
209
|
table.alembic_version_meta_table_uid = version_root
|
|
@@ -1,41 +1,93 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Resolve the selected environment connection for application-owned migrations."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
4
|
|
|
4
5
|
from typing import Any, Literal
|
|
5
6
|
from uuid import UUID
|
|
6
7
|
|
|
7
|
-
from fastapi import APIRouter, Depends, HTTPException
|
|
8
|
+
from fastapi import APIRouter, Depends, HTTPException, Request, Response
|
|
8
9
|
from pydantic import BaseModel, ConfigDict, Field
|
|
10
|
+
from sqlalchemy import select
|
|
9
11
|
from sqlalchemy.orm import Session
|
|
10
12
|
|
|
11
13
|
from api.app.auth.boundary import trusted_actor_facts
|
|
12
14
|
from api.app.auth.local_actor import catalog_session
|
|
15
|
+
from api.app.routes.table_introspection import data_source_provider
|
|
13
16
|
from api.app.routes.table_sql import authorized_table
|
|
17
|
+
from api.backend.backends.migration_connection import migration_connection_description
|
|
18
|
+
from api.backend.domain.data_source_rules import (
|
|
19
|
+
DataSourceAdmissionError,
|
|
20
|
+
require_data_source_access,
|
|
21
|
+
)
|
|
14
22
|
from api.backend.domain.permission_rules import TrustedActorFacts
|
|
23
|
+
from api.backend.integrations.runtime_data_sources import DataSourceIntegrationError
|
|
24
|
+
from api.backend.persistence.grants import GrantRepository
|
|
15
25
|
from api.backend.persistence.locking import lock_catalog
|
|
26
|
+
from api.backend.persistence.models import MetaTable
|
|
16
27
|
|
|
17
|
-
router = APIRouter(prefix=
|
|
28
|
+
router = APIRouter(prefix="/meta-tables", tags=["MetaTables"])
|
|
18
29
|
|
|
19
30
|
|
|
20
31
|
class MigrationRequest(BaseModel):
|
|
21
|
-
model_config = ConfigDict(extra=
|
|
22
|
-
purpose: Literal[
|
|
23
|
-
package: str =
|
|
24
|
-
migration_namespace: str =
|
|
25
|
-
migration_provider_key: str =
|
|
32
|
+
model_config = ConfigDict(extra="forbid")
|
|
33
|
+
purpose: Literal["schema_migration"] = "schema_migration"
|
|
34
|
+
package: str = ""
|
|
35
|
+
migration_namespace: str = ""
|
|
36
|
+
migration_provider_key: str = ""
|
|
26
37
|
ttl_seconds: int = Field(default=900, ge=60, le=3600)
|
|
27
38
|
code_repository_context: dict[str, Any] | None = None
|
|
28
39
|
|
|
29
40
|
|
|
30
|
-
@router.post(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
@router.post("/{table_uid}/migration-connection/")
|
|
42
|
+
def migration_connection(
|
|
43
|
+
table_uid: UUID,
|
|
44
|
+
payload: MigrationRequest,
|
|
45
|
+
request: Request,
|
|
46
|
+
response: Response,
|
|
47
|
+
actor: TrustedActorFacts = Depends(trusted_actor_facts),
|
|
48
|
+
session: Session = Depends(catalog_session),
|
|
49
|
+
sources=Depends(data_source_provider),
|
|
50
|
+
):
|
|
35
51
|
lock_catalog(session)
|
|
36
|
-
authorized_table(session, actor, table_uid, edit=True, reserved_policy=
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
52
|
+
table = authorized_table(session, actor, table_uid, edit=True, reserved_policy="reconcile")
|
|
53
|
+
if (
|
|
54
|
+
table.management_mode != "platform_managed"
|
|
55
|
+
or table.schema_management_mode != "alembic_managed"
|
|
56
|
+
):
|
|
57
|
+
raise HTTPException(409, "MetaTable is not Alembic managed.")
|
|
58
|
+
for field, value in [
|
|
59
|
+
("migration_package", payload.package),
|
|
60
|
+
("migration_namespace", payload.migration_namespace),
|
|
61
|
+
("migration_provider_key", payload.migration_provider_key),
|
|
62
|
+
]:
|
|
63
|
+
if value and value != getattr(table, field):
|
|
64
|
+
raise HTTPException(409, "Migration provider identity does not match.")
|
|
65
|
+
root_uid = table.alembic_version_meta_table_uid or table.uid
|
|
66
|
+
tables = list(
|
|
67
|
+
session.scalars(
|
|
68
|
+
select(MetaTable).where(
|
|
69
|
+
(MetaTable.uid == root_uid) | (MetaTable.alembic_version_meta_table_uid == root_uid)
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
if any(
|
|
74
|
+
not GrantRepository(session).may_access_table(table_uid=item.uid, actor=actor, edit=True)
|
|
75
|
+
for item in tables
|
|
76
|
+
):
|
|
77
|
+
raise HTTPException(403, "Writer access is required for every provider catalog table.")
|
|
78
|
+
try:
|
|
79
|
+
source = sources.get(table.data_source_uid)
|
|
80
|
+
require_data_source_access(source, access="write")
|
|
81
|
+
result = migration_connection_description(source)
|
|
82
|
+
except DataSourceAdmissionError as exc:
|
|
83
|
+
raise HTTPException(exc.status_code, exc.code) from exc
|
|
84
|
+
except DataSourceIntegrationError as exc:
|
|
85
|
+
raise HTTPException(503, "DataSource is unavailable.") from exc
|
|
86
|
+
# Include removed provider models so finalization reconciles dropped tables.
|
|
87
|
+
result["meta_table_uids"] = [str(item.uid) for item in tables if item.uid != root_uid]
|
|
88
|
+
control = getattr(request.app.state, "runtime_control", None)
|
|
89
|
+
if control is not None:
|
|
90
|
+
result.update(control.hold_migration(actor.user_uid))
|
|
91
|
+
response.headers["Cache-Control"] = "no-store"
|
|
92
|
+
response.headers["Pragma"] = "no-cache"
|
|
93
|
+
return result
|
api/app/routes/run_logs.py
CHANGED
|
@@ -14,7 +14,9 @@ from api.app.auth.local_actor import catalog_session
|
|
|
14
14
|
from api.app.routes.update_crud import admitted_update
|
|
15
15
|
from api.backend.domain.permission_rules import TrustedActorFacts
|
|
16
16
|
from api.backend.integrations.run_logs import _query, read_logs
|
|
17
|
-
from api.backend.persistence.
|
|
17
|
+
from api.backend.persistence.grants import GrantRepository
|
|
18
|
+
from api.backend.persistence.models import MetaTable, UpdateNode, UpdateRun
|
|
19
|
+
from api.backend.persistence.run_graphs import MAX_NODES
|
|
18
20
|
from metatables.log_contract import LogPage
|
|
19
21
|
|
|
20
22
|
router = APIRouter(tags=["TimeIndexTableUpdates"])
|
|
@@ -49,6 +51,37 @@ def run_logs(
|
|
|
49
51
|
return read_logs(state, state.log_snapshots, [run], request.query_params, scope=str(run_uid))
|
|
50
52
|
|
|
51
53
|
|
|
54
|
+
@router.get("/table-update-runs/{run_uid}/invocation-logs/", response_model=LogPage)
|
|
55
|
+
def invocation_logs(
|
|
56
|
+
run_uid: UUID,
|
|
57
|
+
request: Request,
|
|
58
|
+
query: Annotated[LogQuery, Query()],
|
|
59
|
+
actor: TrustedActorFacts = Depends(trusted_actor_facts),
|
|
60
|
+
session: Session = Depends(catalog_session),
|
|
61
|
+
):
|
|
62
|
+
"""One time-ordered page across the readable attempts of the selected run's invocation.
|
|
63
|
+
|
|
64
|
+
`run_uid` narrows the page to one attempt of that invocation. A run without a
|
|
65
|
+
saved graph is its own invocation.
|
|
66
|
+
"""
|
|
67
|
+
run = session.get(UpdateRun, run_uid)
|
|
68
|
+
if run is None:
|
|
69
|
+
raise HTTPException(404, "Run not found.")
|
|
70
|
+
admitted_update(session, actor, run.update_uid)
|
|
71
|
+
member = UpdateRun.root_run_uid == run.root_run_uid if run.root_run_uid else UpdateRun.uid == run.uid
|
|
72
|
+
statement = select(UpdateRun).join(UpdateNode, UpdateNode.uid == UpdateRun.update_uid).join(
|
|
73
|
+
MetaTable, MetaTable.uid == UpdateNode.output_table_uid
|
|
74
|
+
).where(member, GrantRepository.table_access_predicate(actor))
|
|
75
|
+
if query.run_uid is not None:
|
|
76
|
+
statement = statement.where(UpdateRun.uid == query.run_uid)
|
|
77
|
+
runs = list(session.scalars(statement.order_by(UpdateRun.started_at, UpdateRun.uid)))
|
|
78
|
+
if not runs:
|
|
79
|
+
raise HTTPException(422, "Run filter is not a readable attempt of this invocation.")
|
|
80
|
+
state = request.app.state.runtime
|
|
81
|
+
return read_logs(state, state.log_snapshots, runs, request.query_params,
|
|
82
|
+
scope=f"invocation:{run.root_run_uid or run.uid}", max_runs=MAX_NODES)
|
|
83
|
+
|
|
84
|
+
|
|
52
85
|
@router.get("/time-index-table-updates/{update_uid}/logs/", response_model=LogPage)
|
|
53
86
|
def update_logs(
|
|
54
87
|
update_uid: UUID,
|
|
@@ -74,7 +74,6 @@ def runtime_context(
|
|
|
74
74
|
|
|
75
75
|
result = {
|
|
76
76
|
"credential_store": state.credential_store.descriptor(),
|
|
77
|
-
"application_migrations_available": bool(getattr(deployment, "application_migration_providers", {})),
|
|
78
77
|
"is_admin": caller.is_admin,
|
|
79
78
|
"user_uid": str(caller.user_uid),
|
|
80
79
|
"local_mode": state.config.local_mode,
|
api/app/routes/update_crud.py
CHANGED
|
@@ -16,6 +16,7 @@ from api.app.auth.local_actor import catalog_session
|
|
|
16
16
|
from api.app.routes.table_response import project_table_response
|
|
17
17
|
from api.app.routes.update_runs import _run_payload
|
|
18
18
|
from api.backend.domain.permission_rules import TrustedActorFacts
|
|
19
|
+
from api.backend.persistence import run_graphs
|
|
19
20
|
from api.backend.persistence.grants import GrantRepository
|
|
20
21
|
from api.backend.persistence.labels import LabelRepository
|
|
21
22
|
from api.backend.persistence.models import (
|
|
@@ -207,7 +208,7 @@ def list_runs(request: Request, actor: TrustedActorFacts = Depends(trusted_actor
|
|
|
207
208
|
item = _run_payload(row)
|
|
208
209
|
graph = session.get(UpdateRunGraph, row.root_run_uid) if row.root_run_uid else None
|
|
209
210
|
saved = next((node for node in graph.snapshot['nodes'] if node['id'] == f'update:{row.update_uid}'), None) if graph else None
|
|
210
|
-
item['updater_label'] = saved['label'] if saved else session.get(UpdateNode, row.update_uid)
|
|
211
|
+
item['updater_label'] = saved['label'] if saved else run_graphs.updater_label(session.get(UpdateNode, row.update_uid))
|
|
211
212
|
item['graph_availability'] = 'available' if graph else 'unavailable'
|
|
212
213
|
if graph is None:
|
|
213
214
|
item['root_run_uid'] = None
|
|
@@ -220,9 +221,12 @@ def get_run(run_uid: UUID, actor: TrustedActorFacts = Depends(trusted_actor_fact
|
|
|
220
221
|
run = session.get(UpdateRun, run_uid)
|
|
221
222
|
if run is None:
|
|
222
223
|
raise HTTPException(404, 'Run not found.')
|
|
223
|
-
admitted_update(session, actor, run.update_uid)
|
|
224
|
+
update = admitted_update(session, actor, run.update_uid)
|
|
224
225
|
result = _run_payload(run)
|
|
225
|
-
|
|
226
|
+
graph = session.get(UpdateRunGraph, run.root_run_uid) if run.root_run_uid else None
|
|
227
|
+
saved = next((node for node in graph.snapshot['nodes'] if node['id'] == f'update:{run.update_uid}'), None) if graph else None
|
|
228
|
+
result['updater_label'] = saved['label'] if saved else run_graphs.updater_label(update)
|
|
229
|
+
if graph is None:
|
|
226
230
|
result.update(root_run_uid=None, graph_availability='unavailable')
|
|
227
231
|
return result
|
|
228
232
|
|
api/backend/backends/catalog.py
CHANGED
|
@@ -167,24 +167,11 @@ class PostgreSQLCatalog:
|
|
|
167
167
|
"SELECT pg_advisory_unlock(hashtext('metatables:bootstrap'))"
|
|
168
168
|
)
|
|
169
169
|
|
|
170
|
-
@contextmanager
|
|
171
|
-
def migration_guard(self, connection):
|
|
172
|
-
from sqlalchemy.orm import Session
|
|
173
|
-
|
|
174
|
-
with Session(bind=connection.engine) as session:
|
|
175
|
-
yield session
|
|
176
|
-
|
|
177
170
|
@contextmanager
|
|
178
171
|
def migration_connection(self, engine):
|
|
179
172
|
with engine.connect() as connection, connection.begin():
|
|
180
173
|
yield connection
|
|
181
174
|
|
|
182
|
-
@contextmanager
|
|
183
|
-
def application_migration_connection(self, engine):
|
|
184
|
-
with self.migration_connection(engine) as connection:
|
|
185
|
-
connection.exec_driver_sql("SET LOCAL search_path TO public")
|
|
186
|
-
yield connection
|
|
187
|
-
|
|
188
175
|
|
|
189
176
|
class SQLiteCatalog(PostgreSQLCatalog):
|
|
190
177
|
default_schema = None
|
|
@@ -192,17 +179,6 @@ class SQLiteCatalog(PostgreSQLCatalog):
|
|
|
192
179
|
def initialize_namespace(self, connection):
|
|
193
180
|
pass
|
|
194
181
|
|
|
195
|
-
@contextmanager
|
|
196
|
-
def migration_guard(self, connection):
|
|
197
|
-
from sqlalchemy.orm import Session
|
|
198
|
-
with Session(bind=connection) as session:
|
|
199
|
-
yield session
|
|
200
|
-
|
|
201
|
-
@contextmanager
|
|
202
|
-
def application_migration_connection(self, engine):
|
|
203
|
-
with self.migration_connection(engine) as connection:
|
|
204
|
-
yield connection
|
|
205
|
-
|
|
206
182
|
def create_engine(self, url, *, native_values=False):
|
|
207
183
|
options = {"timeout": 30, "check_same_thread": False}
|
|
208
184
|
if native_values:
|
|
@@ -173,8 +173,6 @@ class CatalogBackend(Protocol):
|
|
|
173
173
|
def schema(self, name: str | None) -> str | None: ...
|
|
174
174
|
def bootstrap_lock(self, engine: Engine) -> AbstractContextManager[None]: ...
|
|
175
175
|
def migration_connection(self, engine: Engine) -> AbstractContextManager[Connection]: ...
|
|
176
|
-
def application_migration_connection(self, engine: Engine) -> AbstractContextManager[Connection]: ...
|
|
177
|
-
def migration_guard(self, connection: Connection) -> AbstractContextManager[Session]: ...
|
|
178
176
|
def schema_object_state(self, connection: Connection, name: str) -> Any: ...
|
|
179
177
|
def column_type_matches(self, expected: Any, actual: Any, dialect: Any) -> bool: ...
|
|
180
178
|
def index_names(self, inspector: Any, table: str) -> set[str]: ...
|
api/backend/backends/hosted.py
CHANGED
|
@@ -21,11 +21,6 @@ class HostedCatalog(PostgreSQLCatalog):
|
|
|
21
21
|
def initialize_namespace(self, connection):
|
|
22
22
|
pass
|
|
23
23
|
|
|
24
|
-
@contextmanager
|
|
25
|
-
def application_migration_connection(self, engine):
|
|
26
|
-
with self.migration_connection(engine) as connection:
|
|
27
|
-
yield connection
|
|
28
|
-
|
|
29
24
|
def registration_schema(self, source, name):
|
|
30
25
|
return self.physical_schema(source, name)
|
|
31
26
|
|
|
@@ -126,14 +121,6 @@ class MySQLCatalog(HostedCatalog):
|
|
|
126
121
|
]:
|
|
127
122
|
raise CatalogConfigurationError("catalog_index_definition_drift")
|
|
128
123
|
|
|
129
|
-
@contextmanager
|
|
130
|
-
def migration_guard(self, connection):
|
|
131
|
-
from sqlalchemy.orm import Session
|
|
132
|
-
|
|
133
|
-
# Hold catalog admission while implicit DDL commits use a separate connection.
|
|
134
|
-
with Session(connection.engine) as session:
|
|
135
|
-
yield session
|
|
136
|
-
|
|
137
124
|
@contextmanager
|
|
138
125
|
def migration_connection(self, engine):
|
|
139
126
|
# DDL implicitly commits on MySQL. The shared bootstrap journal records
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Describe the configured runtime connection for application-owned Alembic.
|
|
2
|
+
|
|
3
|
+
DDL authority belongs to the configured database login. This does not create a
|
|
4
|
+
role or claim that a direct database connection enforces catalog table grants.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from sqlalchemy.engine import URL
|
|
8
|
+
|
|
9
|
+
from api.backend.backends.registry import engine_descriptor
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def migration_connection_description(source):
|
|
13
|
+
settings = source.connection
|
|
14
|
+
dialect = engine_descriptor(source.class_type).dialect
|
|
15
|
+
tls = {}
|
|
16
|
+
if dialect == "sqlite":
|
|
17
|
+
url = URL.create("sqlite", database=str(settings.path))
|
|
18
|
+
else:
|
|
19
|
+
query = {}
|
|
20
|
+
driver = {
|
|
21
|
+
"postgresql": "postgresql+psycopg2",
|
|
22
|
+
"mysql": "mysql+pymysql",
|
|
23
|
+
"mssql": "mssql+pyodbc",
|
|
24
|
+
}[dialect]
|
|
25
|
+
if dialect == "postgresql":
|
|
26
|
+
query = {"sslmode": settings.ssl_mode, "connect_timeout": "10"}
|
|
27
|
+
elif dialect == "mysql":
|
|
28
|
+
query = {"charset": settings.default_charset or "utf8mb4"}
|
|
29
|
+
else:
|
|
30
|
+
query = {
|
|
31
|
+
"driver": "ODBC Driver 18 for SQL Server",
|
|
32
|
+
"Encrypt": "yes" if settings.encrypt else "no",
|
|
33
|
+
"TrustServerCertificate": "yes" if settings.trust_server_certificate else "no",
|
|
34
|
+
}
|
|
35
|
+
if dialect in {"postgresql", "mysql"}:
|
|
36
|
+
tls = {
|
|
37
|
+
"ssl_mode": settings.ssl_mode,
|
|
38
|
+
"ca_certificate": settings.tls_ca_certificate,
|
|
39
|
+
"client_certificate": settings.tls_client_certificate,
|
|
40
|
+
"client_key": settings.tls_client_key,
|
|
41
|
+
}
|
|
42
|
+
url = URL.create(
|
|
43
|
+
driver,
|
|
44
|
+
username=settings.database_user,
|
|
45
|
+
password=settings.password,
|
|
46
|
+
host=settings.host,
|
|
47
|
+
port=settings.port,
|
|
48
|
+
database=settings.database_name,
|
|
49
|
+
query=query,
|
|
50
|
+
)
|
|
51
|
+
return {
|
|
52
|
+
"ok": True,
|
|
53
|
+
"data_source_uid": str(source.uid),
|
|
54
|
+
"dialect": dialect,
|
|
55
|
+
"credential_kind": "configured_runtime_connection",
|
|
56
|
+
"role_name": None,
|
|
57
|
+
"owner_role_name": None,
|
|
58
|
+
"expires_at": None,
|
|
59
|
+
"uri": url.render_as_string(hide_password=False),
|
|
60
|
+
"tls": tls,
|
|
61
|
+
"default_schema": settings.default_schema,
|
|
62
|
+
}
|
|
@@ -151,7 +151,7 @@ def _hosted(run, capture, query, start, end, budget, jobs):
|
|
|
151
151
|
return rows, "error", bool(rows)
|
|
152
152
|
|
|
153
153
|
|
|
154
|
-
def read_logs(state, cache, runs, params, *, scope):
|
|
154
|
+
def read_logs(state, cache, runs, params, *, scope, max_runs=MAX_RUNS):
|
|
155
155
|
query = _query(params)
|
|
156
156
|
token = params.get("cursor")
|
|
157
157
|
signature = (storage_key(state), scope, query)
|
|
@@ -192,9 +192,9 @@ def read_logs(state, cache, runs, params, *, scope):
|
|
|
192
192
|
)
|
|
193
193
|
|
|
194
194
|
rows, statuses, segments, captures = [], {}, [], []
|
|
195
|
-
budget, hosted_budget, truncated = [0], [0], len(runs) >
|
|
195
|
+
budget, hosted_budget, truncated = [0], [0], len(runs) > max_runs
|
|
196
196
|
jobs = {}
|
|
197
|
-
for run in runs[:
|
|
197
|
+
for run in runs[:max_runs]:
|
|
198
198
|
capture = LogCapture.model_validate(run.log_capture or {"mode": "unavailable"})
|
|
199
199
|
status, found, more = "unavailable", [], False
|
|
200
200
|
if state.config.local_mode and capture.mode == "local":
|
|
@@ -32,6 +32,13 @@ def fingerprint(update_uid, actor, payload):
|
|
|
32
32
|
return sha256(json.dumps(body, sort_keys=True, separators=(",", ":")).encode()).hexdigest()
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
def updater_label(update):
|
|
36
|
+
"""The updater's class name, as graphs and run history label it; its hash otherwise."""
|
|
37
|
+
path = update.build_configuration.get("table_updater_class_import_path", {})
|
|
38
|
+
label = path.get("qualname") if isinstance(path, dict) else None
|
|
39
|
+
return label if isinstance(label, str) else update.update_hash
|
|
40
|
+
|
|
41
|
+
|
|
35
42
|
def _require(condition, message):
|
|
36
43
|
if not condition:
|
|
37
44
|
raise CatalogInvariantError(message)
|
|
@@ -107,10 +114,7 @@ def build_snapshot(session, actor, root_uid, plan):
|
|
|
107
114
|
for uid, update in sorted(updates.items()):
|
|
108
115
|
_require(grants.may_access_table(table_uid=update.output_table_uid, actor=actor, edit=True),
|
|
109
116
|
"Run updater is unavailable")
|
|
110
|
-
|
|
111
|
-
label = path.get("qualname") if isinstance(path, dict) else None
|
|
112
|
-
nodes.append({"id": f"update:{uid}", "uid": uid, "kind": "update",
|
|
113
|
-
"label": label if isinstance(label, str) else update.update_hash,
|
|
117
|
+
nodes.append({"id": f"update:{uid}", "uid": uid, "kind": "update", "label": updater_label(update),
|
|
114
118
|
"update_hash": update.update_hash, "output_table_uid": str(update.output_table_uid),
|
|
115
119
|
"namespace": tables[str(update.output_table_uid)][1]})
|
|
116
120
|
edges.append({"source": f"update:{uid}", "target": f"table:{update.output_table_uid}", "kind": "writes"})
|
|
@@ -265,6 +269,10 @@ def read_graph(session, actor, selected):
|
|
|
265
269
|
grants = GrantRepository(session)
|
|
266
270
|
if root_node is None or not grants.may_access_table(table_uid=root_node.output_table_uid, actor=actor):
|
|
267
271
|
return None
|
|
272
|
+
# Attempt records bound each node's timeline: admission to completion around the
|
|
273
|
+
# calculation window that node_states records.
|
|
274
|
+
attempts = {str(row.uid): row for row in session.scalars(select(UpdateRun).where(UpdateRun.uid.in_(
|
|
275
|
+
[UUID(state["run_uid"]) for state in graph.node_states.values() if state["run_uid"]])))}
|
|
268
276
|
nodes = []
|
|
269
277
|
for saved in graph.snapshot["nodes"]:
|
|
270
278
|
table_uid = UUID(saved.get("output_table_uid") or saved["uid"])
|
|
@@ -276,6 +284,9 @@ def read_graph(session, actor, selected):
|
|
|
276
284
|
if node["kind"] == "update":
|
|
277
285
|
node.update(graph.node_states[node["id"]])
|
|
278
286
|
node["status"] = node["state"]
|
|
287
|
+
attempt = attempts.get(node["run_uid"])
|
|
288
|
+
node["attempt_started_at"] = attempt.started_at if attempt else None
|
|
289
|
+
node["attempt_ended_at"] = attempt.ended_at if attempt else None
|
|
279
290
|
nodes.append(node)
|
|
280
291
|
ids = {node["id"] for node in nodes}
|
|
281
292
|
return {"availability": "available", "run_uid": str(selected.uid), "root_run_uid": str(root.uid),
|
examples/README.md
CHANGED
|
@@ -8,7 +8,7 @@ For one connected walkthrough, start with the [market tutorial](tutorial/README.
|
|
|
8
8
|
|
|
9
9
|
| Asset | What it demonstrates | Required environment |
|
|
10
10
|
| --- | --- | --- |
|
|
11
|
-
| [Local application](local_app/README.md) | Setup, API/Admin launch, explicit bootstrap,
|
|
11
|
+
| [Local application](local_app/README.md) | Setup, API/Admin launch, explicit bootstrap, application-owned migrations and persistent write/read | Installed package, application Git checkout, SDK login; Node/npm for Admin. |
|
|
12
12
|
| [tables.py](tables.py) | Related account and time-index balance contracts | Import/contract checks are offline. |
|
|
13
13
|
| [quickstart.py](quickstart.py) | Retrieve and validate a visible table | Configured API, SDK session, table grant. |
|
|
14
14
|
| [external_table.py](external_table.py) | Register an existing physical relation | API, source access, pre-existing matching table. |
|
examples/local_app/README.md
CHANGED
|
@@ -7,7 +7,7 @@ needs a commit and an `origin` remote. Use Python 3.13+ on macOS or Linux.
|
|
|
7
7
|
```bash
|
|
8
8
|
python -m pip install mainsequence-metatable
|
|
9
9
|
mainsequence login
|
|
10
|
-
metatables init --local
|
|
10
|
+
metatables init --local
|
|
11
11
|
metatables serve --local --admin
|
|
12
12
|
```
|
|
13
13
|
|
|
@@ -22,7 +22,7 @@ In another terminal in the same project and Python environment:
|
|
|
22
22
|
```bash
|
|
23
23
|
metatables --local runtime status
|
|
24
24
|
metatables --local runtime initialize
|
|
25
|
-
metatables --local migrations upgrade --provider
|
|
25
|
+
metatables --local migrations upgrade --provider examples.local_app.migrations:migration
|
|
26
26
|
python -m examples.local_app
|
|
27
27
|
metatables --local meta-table list
|
|
28
28
|
```
|
|
@@ -33,10 +33,9 @@ Expected example output:
|
|
|
33
33
|
[{"key": "hello", "message": "My local MetaTables application"}]
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
The provider
|
|
36
|
+
The client runs the provider to create the table, then finalizes its catalog binding through the API.
|
|
37
37
|
The example resolves that table by identifier, compiles bound SQL for the API's
|
|
38
|
-
selected dialect, upserts one note, and reads it back.
|
|
39
|
-
the client. Repeating it keeps one row. Stop and restart the launcher, then inspect
|
|
38
|
+
selected dialect, upserts one note, and reads it back. Ordinary reads and writes use the API; only migrations open the environment database. Repeating it keeps one row. Stop and restart the launcher, then inspect
|
|
40
39
|
the existing row before any write:
|
|
41
40
|
|
|
42
41
|
```bash
|
|
@@ -49,5 +48,4 @@ Native keyring credentials are the default; for a headless machine, configure th
|
|
|
49
48
|
file credential provider as described in the [local runtime guide](../../docs/operations/local-runtime.md#local-credentials).
|
|
50
49
|
|
|
51
50
|
For your own application, define tables like [Note](tables.py), install the package
|
|
52
|
-
containing your [migration provider](migrations/__init__.py)
|
|
53
|
-
its alias in `configuration.yaml`. See [migration authoring](../../docs/client/define-and-migrate-tables.md).
|
|
51
|
+
containing your [migration provider](migrations/__init__.py) in the application process. See [migration authoring](../../docs/client/define-and-migrate-tables.md).
|
|
@@ -5,22 +5,12 @@ from pathlib import Path
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def setup_metatables():
|
|
8
|
-
from mainsequence.client.exceptions import raise_for_response
|
|
9
|
-
from mainsequence.client.utils import make_request
|
|
10
|
-
|
|
11
8
|
from metatables.endpoint import api_endpoint_scope, resolve_api_endpoint
|
|
12
|
-
from metatables.
|
|
13
|
-
|
|
14
|
-
class MigrationResource(_MetaTablesBaseObjectOrm):
|
|
15
|
-
ENDPOINT = "application-migrations/upgrade/"
|
|
9
|
+
from metatables.runtime import upgrade_application
|
|
16
10
|
|
|
17
11
|
with api_endpoint_scope():
|
|
18
12
|
print(f"Preparing tutorial on MetaTables API: {resolve_api_endpoint().url}", flush=True)
|
|
19
|
-
|
|
20
|
-
r_type="POST", url=MigrationResource.get_object_url(),
|
|
21
|
-
payload={"json": {"provider": "market-tutorial"}}, time_out=(5, 120))
|
|
22
|
-
raise_for_response(response)
|
|
23
|
-
result = response.json()
|
|
13
|
+
result = upgrade_application('examples.tutorial.migrations:migration', timeout=120)
|
|
24
14
|
print(f"Tutorial DataSource: {result['data_source_uid']}; revision: {result['revision']} "
|
|
25
15
|
f"({'migrated' if result['migrated'] else 'already current'})", flush=True)
|
|
26
16
|
return result
|