mainsequence 4.2.16__tar.gz → 4.2.37__tar.gz
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.
- {mainsequence-4.2.16/mainsequence.egg-info → mainsequence-4.2.37}/PKG-INFO +2 -2
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +23 -14
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +53 -42
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/cli.py +0 -3
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/migrations.py +318 -36
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/metatables/core.py +113 -204
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/__init__.py +11 -6
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/migrations.py +280 -351
- mainsequence-4.2.37/mainsequence/meta_tables/schema_names.py +304 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/sqlalchemy_contracts.py +248 -1152
- {mainsequence-4.2.16 → mainsequence-4.2.37/mainsequence.egg-info}/PKG-INFO +2 -2
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence.egg-info/SOURCES.txt +2 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence.egg-info/requires.txt +1 -1
- {mainsequence-4.2.16 → mainsequence-4.2.37}/pyproject.toml +2 -2
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_cli.py +0 -3
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_cli_migrations.py +255 -58
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_meta_table_migrations.py +572 -160
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_meta_tables_client_models.py +243 -219
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_meta_tables_sqlalchemy_contracts.py +376 -351
- mainsequence-4.2.37/tests/test_schema_names.py +104 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/LICENSE +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/README.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/a2a_communication/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/command_center/adapter_from_api/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/command_center/app_components/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/command_center/connections/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/command_center/workspace_design/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/ms-markets/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/agent_scaffold/skills/project_to_agent/SKILL.md +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/__init__.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/__main__.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/bootstrap.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/api.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/config.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/project_status.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/cli/ui.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/__init__.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/agent_runtime_models.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/base.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/client.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/command_center/__init__.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/command_center/app_component.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/command_center/connections.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/command_center/data_models.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/command_center/workspace.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/command_center/workspace_snapshot.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/compute_validation.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/dtype_codec.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/fastapi/__init__.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/fastapi/auth.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/metatables/__init__.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/models_foundry.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/models_helpers.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/models_user.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/client/utils.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/defaults.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/logconf.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/__main__.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/data_nodes/data_nodes.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/data_nodes/models.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/data_nodes/persist_managers.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/data_nodes/run_operations.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/future_registry.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/hashing.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/setup.cfg +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_auth_precedence.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_build_operations_hashing.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_client.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_command_center_app_component_models.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_command_center_data_models.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_command_center_models.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_data_access_mixin_dimension_audit.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_data_node_storage_dimension_queries.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_data_node_update_flow.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_dependency_extras.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_duckdb_interface_dimensions.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_filter_normalization.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_logconf.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_pod_project_resolution.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_project_batch_jobs_from_file.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_run_configuration.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_secret_client_model.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_source_table_configuration.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_sqlite_interface_dimensions.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_update_runner_uid_runtime.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_update_statistics.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_update_uid_guards.py +0 -0
- {mainsequence-4.2.16 → mainsequence-4.2.37}/tests/test_workspace_snapshot.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mainsequence
|
|
3
|
-
Version: 4.2.
|
|
3
|
+
Version: 4.2.37
|
|
4
4
|
Summary: Main Sequence SDK
|
|
5
5
|
Author-email: Main Sequence GmbH <dev@main-sequence.io>
|
|
6
6
|
License: MainSequence GmbH SDK License Agreement
|
|
@@ -68,7 +68,7 @@ Requires-Dist: pydantic
|
|
|
68
68
|
Requires-Dist: pytz
|
|
69
69
|
Requires-Dist: pyyaml
|
|
70
70
|
Requires-Dist: requests
|
|
71
|
-
Requires-Dist: sqlalchemy
|
|
71
|
+
Requires-Dist: sqlalchemy<3,>=2
|
|
72
72
|
Requires-Dist: structlog
|
|
73
73
|
Requires-Dist: tqdm
|
|
74
74
|
Requires-Dist: typer
|
|
@@ -139,7 +139,10 @@ import datetime
|
|
|
139
139
|
from sqlalchemy import DateTime, Float, MetaData
|
|
140
140
|
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
|
141
141
|
|
|
142
|
-
from mainsequence.meta_tables import PlatformTimeIndexMetaData
|
|
142
|
+
from mainsequence.meta_tables import PlatformTimeIndexMetaData, schema_table_name
|
|
143
|
+
|
|
144
|
+
PROJECT_NAME = "<project_name>"
|
|
145
|
+
PRICES_TABLE_NAME = schema_table_name(PROJECT_NAME, "prices")
|
|
143
146
|
|
|
144
147
|
|
|
145
148
|
class Base(DeclarativeBase):
|
|
@@ -147,8 +150,9 @@ class Base(DeclarativeBase):
|
|
|
147
150
|
|
|
148
151
|
|
|
149
152
|
class PricesTable(PlatformTimeIndexMetaData, Base):
|
|
153
|
+
__tablename__ = PRICES_TABLE_NAME
|
|
150
154
|
__metatable_namespace__ = "<domain_namespace>"
|
|
151
|
-
__metatable_identifier__ = "<table_identifier>"
|
|
155
|
+
__metatable_identifier__ = "<project_name>.<table_identifier>"
|
|
152
156
|
__metatable_extra_hash_components__ = {"storage_name": "<stable_storage_name>"}
|
|
153
157
|
__metatable_description__ = (
|
|
154
158
|
"Daily close prices keyed by asset unique identifier for portfolio and "
|
|
@@ -378,23 +382,24 @@ changing it changes the dependency graph and update identity.
|
|
|
378
382
|
|
|
379
383
|
Do not construct dependency graphs dynamically inside `update()`.
|
|
380
384
|
|
|
381
|
-
### 8. Foreign Keys Belong To
|
|
385
|
+
### 8. Foreign Keys Belong To SQLAlchemy And Alembic
|
|
382
386
|
|
|
383
387
|
For new code, model foreign keys on the `PlatformTimeIndexMetaData` storage
|
|
384
|
-
class, or route the storage
|
|
385
|
-
|
|
386
|
-
`
|
|
387
|
-
|
|
388
|
-
|
|
388
|
+
class, or route the storage work to the MetaTable skill. When a DataNode storage
|
|
389
|
+
table needs a platform-managed FK, use normal SQLAlchemy `ForeignKey(...)` /
|
|
390
|
+
`ForeignKeyConstraint(...)` metadata on the storage class. Prefer
|
|
391
|
+
project-prefixed SQLAlchemy table names for explicit FK string targets so
|
|
392
|
+
projects sharing one schema do not collide. Generate those names with
|
|
393
|
+
`schema_table_name(project_or_app, concept)` from `mainsequence.meta_tables`.
|
|
389
394
|
|
|
390
|
-
Do not ask users to
|
|
391
|
-
|
|
392
|
-
|
|
395
|
+
Do not ask users to put FK target `MetaTable.uid` values into DataNode config or
|
|
396
|
+
MetaTable registration contracts. Alembic, SQLAlchemy, and the database own FK
|
|
397
|
+
DDL and physical FK constraint names.
|
|
393
398
|
|
|
394
399
|
Registration of the storage class follows the MetaTable migration lifecycle.
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
400
|
+
The migration provider reserves the MetaTable rows, Alembic renders/applies FK
|
|
401
|
+
DDL from SQLAlchemy metadata, and catalog finalization refreshes the MetaTable
|
|
402
|
+
binding after upgrade.
|
|
398
403
|
|
|
399
404
|
Do not add DataNode configuration fields just to mutate storage metadata.
|
|
400
405
|
|
|
@@ -402,6 +407,10 @@ Do not add DataNode configuration fields just to mutate storage metadata.
|
|
|
402
407
|
|
|
403
408
|
Production-quality table identifiers, descriptions, labels, column docs, and
|
|
404
409
|
foreign-key metadata belong to the storage class/MetaTable registration path.
|
|
410
|
+
Prefix explicit table identifiers, explicit physical table names, and Alembic
|
|
411
|
+
version table names with the project or package name rather than using bare
|
|
412
|
+
names that can collide across projects. Use `schema_table_name(...)` for
|
|
413
|
+
authored SQLAlchemy table names, including DataNode storage tables.
|
|
405
414
|
|
|
406
415
|
Do not put schema or published table metadata on the DataNode configuration.
|
|
407
416
|
|
|
@@ -17,7 +17,7 @@ This skill is for schema-driven application tables registered through TS Manager
|
|
|
17
17
|
- choose `platform_managed` or `external_registered` management mode
|
|
18
18
|
- register platform-managed tables through the model class API
|
|
19
19
|
- build registration requests from resolved SQLAlchemy metadata when inspection is useful
|
|
20
|
-
- define indexes and foreign keys in
|
|
20
|
+
- define indexes and foreign keys in SQLAlchemy metadata for Alembic-owned DDL
|
|
21
21
|
- design governed compiled SQL read and write operations
|
|
22
22
|
- design provider-based Alembic contract evolution for MetaTables
|
|
23
23
|
- run the documented `mainsequence migrations ...` lifecycle for Alembic-backed MetaTable changes
|
|
@@ -122,11 +122,15 @@ Keep the application table model as the authoring source for the neutral table c
|
|
|
122
122
|
|
|
123
123
|
Do not hand-build contract fragments when the SQLAlchemy helper can derive them.
|
|
124
124
|
|
|
125
|
-
### 2. Use
|
|
125
|
+
### 2. Use explicit project-prefixed table names
|
|
126
126
|
|
|
127
127
|
For `platform_managed`, inherit from `PlatformManagedMetaTable`.
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
Declare an explicit project-prefixed SQLAlchemy `__tablename__`. Use
|
|
130
|
+
`schema_table_name(project_or_app, concept)` from `mainsequence.meta_tables` to
|
|
131
|
+
generate that name. The mixin derives only the logical `storage_hash` from
|
|
132
|
+
storage-relevant configuration and table shape; it must not use that hash as the
|
|
133
|
+
SQLAlchemy table name.
|
|
130
134
|
|
|
131
135
|
When a platform-managed table must support in-place contract migrations from its
|
|
132
136
|
first version, use Alembic. Keep the SDK model as a normal
|
|
@@ -152,12 +156,26 @@ table. Do not use it for labels, descriptions, runtime options, test isolation,
|
|
|
152
156
|
backend UIDs, data-source UIDs, or updater scope. Use `hash_namespace` for test
|
|
153
157
|
or experiment isolation.
|
|
154
158
|
|
|
159
|
+
Prefix explicit table identifiers, explicit physical table names, and Alembic
|
|
160
|
+
version table names with the project or package name. Bare names such as
|
|
161
|
+
`Account`, `Asset`, or `alembic_version` can collide across projects sharing an
|
|
162
|
+
organization or database schema. Prefer `schema_table_name(...)` over
|
|
163
|
+
hand-built f-strings so project/app prefixes, bounded length, and separators are
|
|
164
|
+
consistent.
|
|
165
|
+
|
|
155
166
|
Register through the class API:
|
|
156
167
|
|
|
157
168
|
```python
|
|
169
|
+
from mainsequence.meta_tables import PlatformManagedMetaTable, schema_table_name
|
|
170
|
+
|
|
171
|
+
PROJECT_NAME = "sdk_examples"
|
|
172
|
+
ACCOUNT_TABLE_NAME = schema_table_name(PROJECT_NAME, "account")
|
|
173
|
+
|
|
174
|
+
|
|
158
175
|
class Account(PlatformManagedMetaTable, Base):
|
|
176
|
+
__tablename__ = ACCOUNT_TABLE_NAME
|
|
159
177
|
__metatable_namespace__ = "sdk-examples"
|
|
160
|
-
__metatable_identifier__ = "Account"
|
|
178
|
+
__metatable_identifier__ = "sdk_examples.Account"
|
|
161
179
|
__metatable_extra_hash_components__ = {"storage_name": "account"}
|
|
162
180
|
__metatable_description__ = (
|
|
163
181
|
"Customer account master records used to scope balances, holdings, and "
|
|
@@ -210,29 +228,25 @@ Do not add generic labels such as `"meta-table"` or `"platform-managed"` to exam
|
|
|
210
228
|
Do not add a `MAINSEQUENCE_META_TABLE_REGISTER` toggle in platform-managed
|
|
211
229
|
examples. Platform-managed examples should be migration-first.
|
|
212
230
|
|
|
213
|
-
### 3.
|
|
214
|
-
|
|
215
|
-
Foreign-key contracts reference the target `MetaTable` UID.
|
|
231
|
+
### 3. Keep foreign keys in SQLAlchemy/Alembic metadata
|
|
216
232
|
|
|
217
|
-
For `PlatformManagedMetaTable`, define foreign keys with
|
|
218
|
-
`
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
uses the target `MetaTable.uid` in the child FK contract.
|
|
233
|
+
For `PlatformManagedMetaTable`, define foreign keys with normal SQLAlchemy
|
|
234
|
+
`ForeignKey(...)` / `ForeignKeyConstraint(...)` metadata. Do not write explicit
|
|
235
|
+
target `MetaTable.uid` maps in the platform-managed path. Migration is the
|
|
236
|
+
lifecycle path: the SDK reserves provider MetaTable rows, Alembic renders and
|
|
237
|
+
applies FK/index DDL from SQLAlchemy metadata, and finalization refreshes the
|
|
238
|
+
catalog after upgrade.
|
|
224
239
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
column is attached to the SQLAlchemy table.
|
|
240
|
+
Prefer project-prefixed SQLAlchemy table names for explicit FK string targets.
|
|
241
|
+
Alembic, SQLAlchemy, and the database own physical FK/index names unless the
|
|
242
|
+
project explicitly names them in SQLAlchemy.
|
|
229
243
|
|
|
230
244
|
Use this pattern:
|
|
231
245
|
|
|
232
246
|
```python
|
|
233
247
|
account_uid: Mapped[uuid.UUID] = mapped_column(
|
|
234
248
|
Uuid,
|
|
235
|
-
|
|
249
|
+
ForeignKey("public.sdk_examples__account.uid", ondelete="RESTRICT"),
|
|
236
250
|
nullable=False,
|
|
237
251
|
)
|
|
238
252
|
```
|
|
@@ -249,21 +263,19 @@ migration = AlembicMetaTableMigration(
|
|
|
249
263
|
)
|
|
250
264
|
```
|
|
251
265
|
|
|
252
|
-
Migration tooling
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
a clear error for recursive registration cycles.
|
|
266
|
+
Migration tooling reserves provider MetaTable rows in the provider-declared
|
|
267
|
+
model order. Include related parent and child models in the same selected
|
|
268
|
+
provider when Alembic must create or evolve their FK DDL.
|
|
256
269
|
|
|
257
|
-
For `external_registered`,
|
|
258
|
-
|
|
259
|
-
|
|
270
|
+
For `external_registered`, register each external table contract directly. Do
|
|
271
|
+
not encode FK target MetaTable UIDs in the child registration request; FKs are
|
|
272
|
+
database DDL/introspection metadata, not SDK registration contract fields:
|
|
260
273
|
|
|
261
274
|
```python
|
|
262
275
|
account_meta_table = MetaTable.register(account_request)
|
|
263
276
|
asset_request = external_registered_registration_request_from_sqlalchemy_model(
|
|
264
277
|
Asset,
|
|
265
278
|
data_source_uid=data_source_uid,
|
|
266
|
-
target_meta_tables={Account: account_meta_table},
|
|
267
279
|
)
|
|
268
280
|
asset_meta_table = MetaTable.register(asset_request)
|
|
269
281
|
```
|
|
@@ -288,18 +300,19 @@ For contract evolution, define or update one selected
|
|
|
288
300
|
- set `package`, `migration_namespace`, `script_location`, and `target_metadata`
|
|
289
301
|
- set `alembic_registry` to an `AlembicVersionMetaTable` subclass
|
|
290
302
|
- list the post-apply catalog scope in `metatable_models`
|
|
291
|
-
- generate
|
|
303
|
+
- generate revisions, apply migrations, and refresh catalog bindings
|
|
292
304
|
through `mainsequence migrations ...` commands
|
|
293
305
|
|
|
294
306
|
`alembic_version_meta_table_uid` is the UID of the catalog binding for Alembic's
|
|
295
307
|
version table. It is not the UID of the table being migrated.
|
|
296
308
|
|
|
297
|
-
Application MetaTable catalog sync resolves existing rows by
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
309
|
+
Application MetaTable catalog sync resolves existing rows by the authored
|
|
310
|
+
SQLAlchemy table name used by the provider model. Keep that table name stable
|
|
311
|
+
when a class is renamed or moved but must keep the same platform identity.
|
|
312
|
+
When declaring an explicit identifier, explicit physical table name, or Alembic
|
|
313
|
+
version table name, prefix it with the project or package name rather than using
|
|
314
|
+
a bare table name. Use `schema_table_name(project_or_app, concept)` for the
|
|
315
|
+
physical table and Alembic version table names.
|
|
303
316
|
|
|
304
317
|
Do not ask users to construct backend migration payloads, call low-level
|
|
305
318
|
migration request models, or use SDK helper functions directly. The backend
|
|
@@ -352,9 +365,8 @@ When reviewing an existing MetaTable workflow, look for:
|
|
|
352
365
|
- backend-managed examples that use namespace environment variables instead of a plain `sdk-examples` namespace
|
|
353
366
|
- duplicate schema sources outside SQLAlchemy table metadata
|
|
354
367
|
- external tables registered with unstable physical names
|
|
355
|
-
- platform-managed examples that
|
|
356
|
-
|
|
357
|
-
- external child registrations that do not map foreign-key targets to registered parent `MetaTable.uid` values
|
|
368
|
+
- platform-managed examples that try to sequence parent registration through FK metadata
|
|
369
|
+
- external child registrations that try to encode FK target MetaTable UIDs in registration contracts
|
|
358
370
|
- contract changes attempted through normal registration instead of an Alembic migration
|
|
359
371
|
- migration work that asks users to define backend payloads, artifact rows, or SDK request objects
|
|
360
372
|
- compiled SQL operations without complete table scope
|
|
@@ -369,9 +381,9 @@ Do not claim success until you have checked:
|
|
|
369
381
|
- the table has an intention-rich `__metatable_description__`
|
|
370
382
|
- every mapped column has an intention-rich `info.description`
|
|
371
383
|
- indexes are intentional
|
|
372
|
-
- foreign keys
|
|
384
|
+
- foreign keys are present in SQLAlchemy metadata for Alembic when required
|
|
373
385
|
- management mode is correct
|
|
374
|
-
-
|
|
386
|
+
- authored physical names are explicit, project-prefixed SQLAlchemy table names
|
|
375
387
|
- registration returns a `MetaTable.uid`
|
|
376
388
|
- compiled SQL operations declare table scope
|
|
377
389
|
- migrations use Alembic-rendered SQL
|
|
@@ -384,9 +396,8 @@ Do not claim success until you have checked:
|
|
|
384
396
|
For related tables, also check:
|
|
385
397
|
|
|
386
398
|
- aliases are readable
|
|
387
|
-
- platform-managed child
|
|
388
|
-
|
|
389
|
-
- external child registration requests map FK targets to the registered parent UIDs
|
|
399
|
+
- platform-managed child tables and parent tables are included in the selected migration provider
|
|
400
|
+
- FK target strings use stable project-prefixed SQLAlchemy table names where explicit strings are authored
|
|
390
401
|
- query results still match the expected response contract
|
|
391
402
|
|
|
392
403
|
## This Skill Must Stop And Escalate When
|
|
@@ -7038,9 +7038,6 @@ def _meta_table_detail_impl(meta_table_uid: str, timeout: int | None) -> None:
|
|
|
7038
7038
|
("Contract Version", str(meta_table.get("contract_version") or "-")),
|
|
7039
7039
|
("Table Contract", _format_json_value(meta_table.get("table_contract"))),
|
|
7040
7040
|
("Columns", _format_json_value(meta_table.get("columns"))),
|
|
7041
|
-
("Indexes", _format_json_value(meta_table.get("indexes_meta"))),
|
|
7042
|
-
("Foreign Keys", _format_json_value(meta_table.get("foreign_keys"))),
|
|
7043
|
-
("Incoming FKs", _format_json_value(meta_table.get("incoming_fks"))),
|
|
7044
7041
|
("Introspection", _format_json_value(meta_table.get("introspection_snapshot"))),
|
|
7045
7042
|
],
|
|
7046
7043
|
)
|