mainsequence 6.0.40__tar.gz → 6.0.41__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-6.0.40/mainsequence.egg-info → mainsequence-6.0.41}/PKG-INFO +1 -1
- {mainsequence-6.0.40 → mainsequence-6.0.41}/agent_scaffold/skills/data_access/exploration/SKILL.md +3 -4
- {mainsequence-6.0.40 → mainsequence-6.0.41}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +2 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +4 -1
- {mainsequence-6.0.40 → mainsequence-6.0.41}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +4 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/cli.py +0 -65
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/base.py +95 -4
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/metatables/core.py +76 -16
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/models_foundry.py +76 -8
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/models_helpers.py +9 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/project_context.py +19 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41/mainsequence.egg-info}/PKG-INFO +1 -1
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence.egg-info/SOURCES.txt +1 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/pyproject.toml +1 -1
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_cli.py +22 -8
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_cli_migrations.py +2 -1
- mainsequence-6.0.41/tests/test_environment_resource_context.py +168 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_filter_normalization.py +72 -34
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_meta_tables_client_models.py +58 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_project_runtime_context.py +35 -0
- mainsequence-6.0.41/tests/test_secret_client_model.py +18 -0
- mainsequence-6.0.40/tests/test_secret_client_model.py +0 -11
- {mainsequence-6.0.40 → mainsequence-6.0.41}/LICENSE +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/README.md +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/agent_scaffold/skills/maintenance/project-maintenance/SKILL.md +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/agent_scaffold/skills/sdk_project_execution/SKILL.md +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/__init__.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/__main__.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/bootstrap.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/api.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/config.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/migrations.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/project_status.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/cli/ui.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/__init__.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/agent_runtime_models.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/client.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/compute_validation.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/dtype_codec.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/metatables/__init__.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/models_user.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/client/utils.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/defaults.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/logconf.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/__init__.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/__main__.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/data_nodes/data_nodes.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/data_nodes/models.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/data_nodes/persist_managers.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/data_nodes/run_operations.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/future_registry.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/hashing.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/migrations/__init__.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/migrations/alembic.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/migrations/env.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/migrations/provider.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/migrations/registry.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/schema_names.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/project_skills.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence/scaffold_skills.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence.egg-info/requires.txt +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/setup.cfg +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_auth_precedence.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_build_operations_hashing.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_canonical_api_route_contract.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_client.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_data_access_mixin_dimension_audit.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_data_node_storage_dimension_queries.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_data_node_update_flow.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_dependency_extras.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_duckdb_interface_dimensions.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_instrumentation.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_local_ops.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_logconf.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_meta_table_migrations.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_notification_uid_contract.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_pod_project_resolution.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_project_batch_jobs_from_file.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_project_branch_contract.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_project_skills.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_run_configuration.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_scaffold_skills.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_schema_names.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_source_table_configuration.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_sqlite_interface_dimensions.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_ssh_utils.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_update_runner_uid_runtime.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_update_statistics.py +0 -0
- {mainsequence-6.0.40 → mainsequence-6.0.41}/tests/test_update_uid_guards.py +0 -0
{mainsequence-6.0.40 → mainsequence-6.0.41}/agent_scaffold/skills/data_access/exploration/SKILL.md
RENAMED
|
@@ -156,10 +156,9 @@ field to filter by:
|
|
|
156
156
|
|
|
157
157
|
Collection listing is scoped to one Organization Environment. Inside a
|
|
158
158
|
registered project checkout, the CLI derives that scope from the process-frozen
|
|
159
|
-
Git-resolved ProjectBranch.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
`organization_project_environment_uid=<ENVIRONMENT_UID>` filter.
|
|
159
|
+
Git-resolved ProjectBranch. Do not pass an Environment UID or branch UID. On an
|
|
160
|
+
unregistered branch, table operations fail when they require ProjectBranch
|
|
161
|
+
context while unrelated local development remains available.
|
|
163
162
|
|
|
164
163
|
Column lookup is also a different path. Use it only for schema-name discovery,
|
|
165
164
|
not as the default dataset discovery flow:
|
|
@@ -72,6 +72,8 @@ Before changing code, collect or infer:
|
|
|
72
72
|
- who owns the MetaTable catalog lifecycle
|
|
73
73
|
- who owns physical DDL: TS Manager, Alembic, or an external authority
|
|
74
74
|
- for `external_registered`, the target canonical `DataSource` UID
|
|
75
|
+
- the actual current Git branch; the SDK resolves its registered `ProjectBranch`
|
|
76
|
+
and Environment, and the user must not provide either UID
|
|
75
77
|
- for contract changes, the selected `AlembicMetaTableMigration` provider or provider module path
|
|
76
78
|
- for contract changes, the provider's `AlembicVersionMetaTable` root and whether it has been reserved
|
|
77
79
|
- for contract changes, the intended Alembic revision, parent/current revision, target revision, and updated SQLAlchemy declarations
|
|
@@ -158,7 +158,10 @@ Do not downgrade a secret into a constant for convenience.
|
|
|
158
158
|
|
|
159
159
|
### 6. `Constant` and `Secret` names are unique configuration identities
|
|
160
160
|
|
|
161
|
-
Treat `Constant.name` and `Secret.name` as unique
|
|
161
|
+
Treat `Constant.name` and `Secret.name` as unique Environment-level
|
|
162
|
+
configuration keys. Project-facing SDK and CLI operations derive the
|
|
163
|
+
Environment from the process-frozen current Git branch and registered
|
|
164
|
+
`ProjectBranch`. Never ask the user to provide an Environment UID or branch UID.
|
|
162
165
|
|
|
163
166
|
For creation or sync tasks:
|
|
164
167
|
|
|
@@ -195,6 +195,10 @@ push alone does not prove deployment success.
|
|
|
195
195
|
|
|
196
196
|
Use `Artifact` when the operational unit is a file.
|
|
197
197
|
|
|
198
|
+
Artifact and Bucket operations derive their Organization Environment from the
|
|
199
|
+
process-frozen current Git branch and registered `ProjectBranch`. Do not ask the
|
|
200
|
+
user to select an Environment UID or branch UID.
|
|
201
|
+
|
|
198
202
|
Examples:
|
|
199
203
|
|
|
200
204
|
- vendor drops
|
|
@@ -1320,47 +1320,6 @@ def _merge_cli_filter_alias(
|
|
|
1320
1320
|
return merged
|
|
1321
1321
|
|
|
1322
1322
|
|
|
1323
|
-
def _scope_table_collection_filters(
|
|
1324
|
-
filters: dict[str, object],
|
|
1325
|
-
*,
|
|
1326
|
-
organization_project_environment_uid: object | None,
|
|
1327
|
-
command_label: str,
|
|
1328
|
-
) -> dict[str, object]:
|
|
1329
|
-
filter_key = "organization_project_environment_uid"
|
|
1330
|
-
scoped = _merge_cli_filter_alias(
|
|
1331
|
-
filters,
|
|
1332
|
-
filter_key=filter_key,
|
|
1333
|
-
value=organization_project_environment_uid,
|
|
1334
|
-
option_name="organization-project-environment-uid",
|
|
1335
|
-
)
|
|
1336
|
-
if filter_key in scoped:
|
|
1337
|
-
return scoped
|
|
1338
|
-
|
|
1339
|
-
try:
|
|
1340
|
-
context = require_project_branch_context(
|
|
1341
|
-
command_label,
|
|
1342
|
-
context=get_project_runtime_context(),
|
|
1343
|
-
)
|
|
1344
|
-
except ProjectRuntimeContextError as exc:
|
|
1345
|
-
error(
|
|
1346
|
-
f"{command_label} requires an Organization Environment scope. "
|
|
1347
|
-
"Run inside a registered ProjectBranch checkout or pass "
|
|
1348
|
-
"`--organization-project-environment-uid`."
|
|
1349
|
-
)
|
|
1350
|
-
raise typer.Exit(1) from exc
|
|
1351
|
-
|
|
1352
|
-
environment_uid = str(context.organization_project_environment_uid or "").strip()
|
|
1353
|
-
if not environment_uid:
|
|
1354
|
-
error(
|
|
1355
|
-
f"{command_label} cannot resolve an Organization Environment from "
|
|
1356
|
-
"the active ProjectBranch."
|
|
1357
|
-
)
|
|
1358
|
-
raise typer.Exit(1)
|
|
1359
|
-
|
|
1360
|
-
scoped[filter_key] = environment_uid
|
|
1361
|
-
return scoped
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
1323
|
def _require_item_uid(item: dict, *, prompt_label: str) -> str:
|
|
1365
1324
|
uid = str(item.get("uid") or "").strip()
|
|
1366
1325
|
if not uid:
|
|
@@ -4466,7 +4425,6 @@ def _data_node_storage_list_impl(
|
|
|
4466
4425
|
filter_entries: list[str] | None,
|
|
4467
4426
|
show_filters: bool,
|
|
4468
4427
|
data_source_uid: str | None = None,
|
|
4469
|
-
organization_project_environment_uid: object | None = None,
|
|
4470
4428
|
) -> None:
|
|
4471
4429
|
filters = _resolve_cli_list_filters(
|
|
4472
4430
|
model_ref=DATA_NODE_STORAGE_MODEL_REF,
|
|
@@ -4481,11 +4439,6 @@ def _data_node_storage_list_impl(
|
|
|
4481
4439
|
option_name="data-source-uid",
|
|
4482
4440
|
)
|
|
4483
4441
|
_require_login()
|
|
4484
|
-
filters = _scope_table_collection_filters(
|
|
4485
|
-
filters,
|
|
4486
|
-
organization_project_environment_uid=organization_project_environment_uid,
|
|
4487
|
-
command_label="Data Node Storage listing",
|
|
4488
|
-
)
|
|
4489
4442
|
|
|
4490
4443
|
try:
|
|
4491
4444
|
storages = list_data_node_storages(timeout=timeout, filters=filters)
|
|
@@ -4519,7 +4472,6 @@ def _meta_table_list_impl(
|
|
|
4519
4472
|
filter_entries: list[str] | None,
|
|
4520
4473
|
show_filters: bool,
|
|
4521
4474
|
data_source_uid: str | None = None,
|
|
4522
|
-
organization_project_environment_uid: object | None = None,
|
|
4523
4475
|
) -> None:
|
|
4524
4476
|
filters = _resolve_cli_list_filters(
|
|
4525
4477
|
model_ref=META_TABLE_MODEL_REF,
|
|
@@ -4534,11 +4486,6 @@ def _meta_table_list_impl(
|
|
|
4534
4486
|
option_name="data-source-uid",
|
|
4535
4487
|
)
|
|
4536
4488
|
_require_login()
|
|
4537
|
-
filters = _scope_table_collection_filters(
|
|
4538
|
-
filters,
|
|
4539
|
-
organization_project_environment_uid=organization_project_environment_uid,
|
|
4540
|
-
command_label="MetaTable listing",
|
|
4541
|
-
)
|
|
4542
4489
|
|
|
4543
4490
|
try:
|
|
4544
4491
|
meta_tables = list_meta_tables(timeout=timeout, filters=filters)
|
|
@@ -6067,11 +6014,6 @@ def meta_table_list_cmd(
|
|
|
6067
6014
|
data_source_uid: str | None = typer.Option(
|
|
6068
6015
|
None, "--data-source-uid", help="Filter by data source UID."
|
|
6069
6016
|
),
|
|
6070
|
-
organization_project_environment_uid: uuid.UUID | None = typer.Option(
|
|
6071
|
-
None,
|
|
6072
|
-
"--organization-project-environment-uid",
|
|
6073
|
-
help=("Organization Environment scope. Defaults to the active Git-resolved ProjectBranch."),
|
|
6074
|
-
),
|
|
6075
6017
|
filter_entries: list[str] | None = typer.Option(None, "--filter", help=LIST_FILTER_OPTION_HELP),
|
|
6076
6018
|
show_filters: bool = typer.Option(
|
|
6077
6019
|
False, "--show-filters", help="Show the filters supported by this list command and exit."
|
|
@@ -6088,7 +6030,6 @@ def meta_table_list_cmd(
|
|
|
6088
6030
|
filter_entries=filter_entries,
|
|
6089
6031
|
show_filters=show_filters,
|
|
6090
6032
|
data_source_uid=data_source_uid,
|
|
6091
|
-
organization_project_environment_uid=organization_project_environment_uid,
|
|
6092
6033
|
)
|
|
6093
6034
|
|
|
6094
6035
|
|
|
@@ -6359,11 +6300,6 @@ def data_node_storage_list_cmd(
|
|
|
6359
6300
|
data_source_uid: str | None = typer.Option(
|
|
6360
6301
|
None, "--data-source-uid", help="Filter by data source UID."
|
|
6361
6302
|
),
|
|
6362
|
-
organization_project_environment_uid: uuid.UUID | None = typer.Option(
|
|
6363
|
-
None,
|
|
6364
|
-
"--organization-project-environment-uid",
|
|
6365
|
-
help=("Organization Environment scope. Defaults to the active Git-resolved ProjectBranch."),
|
|
6366
|
-
),
|
|
6367
6303
|
filter_entries: list[str] | None = typer.Option(None, "--filter", help=LIST_FILTER_OPTION_HELP),
|
|
6368
6304
|
show_filters: bool = typer.Option(
|
|
6369
6305
|
False, "--show-filters", help="Show the filters supported by this list command and exit."
|
|
@@ -6395,7 +6331,6 @@ def data_node_storage_list_cmd(
|
|
|
6395
6331
|
filter_entries=filter_entries,
|
|
6396
6332
|
show_filters=show_filters,
|
|
6397
6333
|
data_source_uid=data_source_uid,
|
|
6398
|
-
organization_project_environment_uid=organization_project_environment_uid,
|
|
6399
6334
|
)
|
|
6400
6335
|
|
|
6401
6336
|
|
|
@@ -97,6 +97,26 @@ class CurrentProjectBranchCollectionMixin:
|
|
|
97
97
|
return list(cls.iter_filter_admin(timeout=timeout, **kwargs))
|
|
98
98
|
|
|
99
99
|
|
|
100
|
+
class CurrentProjectEnvironmentResourceMixin:
|
|
101
|
+
"""Scope project-facing Environment resources to the frozen Git context."""
|
|
102
|
+
|
|
103
|
+
SDK_OWNED_CONTEXT_FIELDS: ClassVar[frozenset[str]] = frozenset(
|
|
104
|
+
{"organization_project_environment_uid"}
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
@classmethod
|
|
108
|
+
def _sdk_owned_query_context(cls, operation: str) -> dict[str, str]:
|
|
109
|
+
from mainsequence.project_context import resolve_project_environment_uid
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
"organization_project_environment_uid": resolve_project_environment_uid(operation)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@classmethod
|
|
116
|
+
def _sdk_owned_create_context(cls, operation: str) -> dict[str, str]:
|
|
117
|
+
return cls._sdk_owned_query_context(operation)
|
|
118
|
+
|
|
119
|
+
|
|
100
120
|
class BaseObjectOrm:
|
|
101
121
|
FILTERSET_FIELDS: ClassVar[dict[str, list[str]] | None] = None
|
|
102
122
|
FILTER_VALUE_NORMALIZERS: ClassVar[dict[str, str | Callable[..., Any]]] = {}
|
|
@@ -105,6 +125,7 @@ class BaseObjectOrm:
|
|
|
105
125
|
DESTROY_QUERY_PARAMS: ClassVar[dict[str, str | Callable[..., Any]] | None] = None
|
|
106
126
|
DESTROY_QUERY_PARAM_DESCRIPTIONS: ClassVar[dict[str, str] | None] = None
|
|
107
127
|
PUBLIC_LOOKUP_FIELD: ClassVar[str] = "uid"
|
|
128
|
+
SDK_OWNED_CONTEXT_FIELDS: ClassVar[frozenset[str]] = frozenset()
|
|
108
129
|
|
|
109
130
|
END_POINTS = {
|
|
110
131
|
"User": "users",
|
|
@@ -154,6 +175,37 @@ class BaseObjectOrm:
|
|
|
154
175
|
s = session
|
|
155
176
|
return s
|
|
156
177
|
|
|
178
|
+
@classmethod
|
|
179
|
+
def _sdk_owned_query_context(cls, operation: str) -> dict[str, Any]:
|
|
180
|
+
return {}
|
|
181
|
+
|
|
182
|
+
@classmethod
|
|
183
|
+
def _sdk_owned_create_context(cls, operation: str) -> dict[str, Any]:
|
|
184
|
+
return {}
|
|
185
|
+
|
|
186
|
+
@classmethod
|
|
187
|
+
def _reject_sdk_context_overrides(
|
|
188
|
+
cls,
|
|
189
|
+
values: dict[str, Any],
|
|
190
|
+
*,
|
|
191
|
+
operation: str,
|
|
192
|
+
) -> None:
|
|
193
|
+
overridden = sorted(set(values) & set(cls.SDK_OWNED_CONTEXT_FIELDS))
|
|
194
|
+
if overridden:
|
|
195
|
+
raise ValueError(
|
|
196
|
+
f"{operation} cannot override SDK-resolved context field(s): "
|
|
197
|
+
f"{', '.join(overridden)}."
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
@classmethod
|
|
201
|
+
def _with_sdk_owned_create_context(
|
|
202
|
+
cls,
|
|
203
|
+
operation: str,
|
|
204
|
+
values: dict[str, Any],
|
|
205
|
+
) -> dict[str, Any]:
|
|
206
|
+
cls._reject_sdk_context_overrides(values, operation=operation)
|
|
207
|
+
return {**values, **cls._sdk_owned_create_context(operation)}
|
|
208
|
+
|
|
157
209
|
@property
|
|
158
210
|
def s(self):
|
|
159
211
|
s = self.build_session()
|
|
@@ -468,11 +520,19 @@ class BaseObjectOrm:
|
|
|
468
520
|
"""
|
|
469
521
|
Generator variant: yields objects across all pages without accumulating into memory.
|
|
470
522
|
"""
|
|
523
|
+
operation = f"{cls.__name__}.filter"
|
|
524
|
+
cls._reject_sdk_context_overrides(kwargs, operation=operation)
|
|
471
525
|
filter_kwargs, read_query_kwargs = cls._split_filter_and_read_query_kwargs(kwargs)
|
|
472
526
|
normalized_filters = cls._normalize_filter_kwargs(filter_kwargs)
|
|
473
527
|
normalized_read_query = cls._normalize_read_query_kwargs(read_query_kwargs)
|
|
474
528
|
base_url = cls.get_object_url()
|
|
475
|
-
params = cls._parse_parameters_filter(
|
|
529
|
+
params = cls._parse_parameters_filter(
|
|
530
|
+
{
|
|
531
|
+
**normalized_filters,
|
|
532
|
+
**normalized_read_query,
|
|
533
|
+
**cls._sdk_owned_query_context(operation),
|
|
534
|
+
}
|
|
535
|
+
)
|
|
476
536
|
|
|
477
537
|
next_url = f"{base_url}/"
|
|
478
538
|
yielded = 0
|
|
@@ -534,6 +594,8 @@ class BaseObjectOrm:
|
|
|
534
594
|
Raises Exception if multiple or unexpected data is returned.
|
|
535
595
|
"""
|
|
536
596
|
if pk is not None:
|
|
597
|
+
operation = f"{cls.__name__}.get"
|
|
598
|
+
cls._reject_sdk_context_overrides(filters, operation=operation)
|
|
537
599
|
base_url = cls.get_object_url()
|
|
538
600
|
detail_url = f"{base_url}/{pk}/"
|
|
539
601
|
_, read_query_kwargs = cls._split_filter_and_read_query_kwargs(filters)
|
|
@@ -541,7 +603,11 @@ class BaseObjectOrm:
|
|
|
541
603
|
extra_params = {
|
|
542
604
|
key: value for key, value in filters.items() if key not in read_query_kwargs
|
|
543
605
|
}
|
|
544
|
-
params = {
|
|
606
|
+
params = {
|
|
607
|
+
**extra_params,
|
|
608
|
+
**normalized_read_query,
|
|
609
|
+
**cls._sdk_owned_query_context(operation),
|
|
610
|
+
}
|
|
545
611
|
|
|
546
612
|
r = make_request(
|
|
547
613
|
s=cls.build_session(),
|
|
@@ -585,7 +651,10 @@ class BaseObjectOrm:
|
|
|
585
651
|
@classmethod
|
|
586
652
|
def create(cls, timeout=None, files=None, *args, **kwargs):
|
|
587
653
|
base_url = cls.get_object_url()
|
|
588
|
-
|
|
654
|
+
operation = f"{cls.__name__}.create"
|
|
655
|
+
data = cls.serialize_for_json(
|
|
656
|
+
cls._with_sdk_owned_create_context(operation, dict(kwargs))
|
|
657
|
+
)
|
|
589
658
|
payload = {"json": data}
|
|
590
659
|
if files:
|
|
591
660
|
payload["files"] = files
|
|
@@ -604,6 +673,8 @@ class BaseObjectOrm:
|
|
|
604
673
|
@classmethod
|
|
605
674
|
def _destroy_by_reference(cls, public_reference, *args, timeout=None, **kwargs):
|
|
606
675
|
base_url = cls.get_object_url()
|
|
676
|
+
operation = f"{cls.__name__}.delete"
|
|
677
|
+
cls._reject_sdk_context_overrides(kwargs, operation=operation)
|
|
607
678
|
payload: dict[str, Any] = {}
|
|
608
679
|
|
|
609
680
|
if getattr(cls, "DESTROY_QUERY_PARAMS", None):
|
|
@@ -615,6 +686,10 @@ class BaseObjectOrm:
|
|
|
615
686
|
if data:
|
|
616
687
|
payload["json"] = data
|
|
617
688
|
|
|
689
|
+
query_context = cls._sdk_owned_query_context(operation)
|
|
690
|
+
if query_context:
|
|
691
|
+
payload.setdefault("params", {}).update(query_context)
|
|
692
|
+
|
|
618
693
|
r = make_request(
|
|
619
694
|
s=cls.build_session(),
|
|
620
695
|
loaders=cls.LOADERS,
|
|
@@ -634,8 +709,13 @@ class BaseObjectOrm:
|
|
|
634
709
|
def _patch_by_reference(cls, public_reference, *args, _into=None, **kwargs):
|
|
635
710
|
base_url = cls.get_object_url()
|
|
636
711
|
url = f"{base_url}/{public_reference}/"
|
|
712
|
+
operation = f"{cls.__name__}.patch"
|
|
713
|
+
cls._reject_sdk_context_overrides(kwargs, operation=operation)
|
|
637
714
|
data = cls.serialize_for_json(kwargs)
|
|
638
715
|
payload = {"json": data}
|
|
716
|
+
query_context = cls._sdk_owned_query_context(operation)
|
|
717
|
+
if query_context:
|
|
718
|
+
payload["params"] = query_context
|
|
639
719
|
|
|
640
720
|
r = make_request(
|
|
641
721
|
s=cls.build_session(),
|
|
@@ -769,7 +849,18 @@ class DetailActionObjectMixin:
|
|
|
769
849
|
expected_statuses: tuple[int, ...] = (200,),
|
|
770
850
|
empty_response: Any = None,
|
|
771
851
|
) -> Any:
|
|
772
|
-
payload = payload or {}
|
|
852
|
+
payload = dict(payload or {})
|
|
853
|
+
query_context = type(self)._sdk_owned_query_context(
|
|
854
|
+
f"{type(self).__name__}.{action_name}"
|
|
855
|
+
)
|
|
856
|
+
if query_context:
|
|
857
|
+
params = dict(payload.get("params") or {})
|
|
858
|
+
type(self)._reject_sdk_context_overrides(
|
|
859
|
+
params,
|
|
860
|
+
operation=f"{type(self).__name__}.{action_name}",
|
|
861
|
+
)
|
|
862
|
+
params.update(query_context)
|
|
863
|
+
payload["params"] = params
|
|
773
864
|
response = make_request(
|
|
774
865
|
s=type(self).build_session(),
|
|
775
866
|
loaders=type(self).LOADERS,
|
|
@@ -33,9 +33,16 @@ from mainsequence.project_context import (
|
|
|
33
33
|
get_project_runtime_context,
|
|
34
34
|
require_project_branch_context,
|
|
35
35
|
require_project_metatables_data_source,
|
|
36
|
+
resolve_project_environment_uid,
|
|
36
37
|
)
|
|
37
38
|
|
|
38
|
-
from ..base import
|
|
39
|
+
from ..base import (
|
|
40
|
+
BaseObjectOrm,
|
|
41
|
+
BasePydanticModel,
|
|
42
|
+
CurrentProjectEnvironmentResourceMixin,
|
|
43
|
+
LabelableObjectMixin,
|
|
44
|
+
ShareableObjectMixin,
|
|
45
|
+
)
|
|
39
46
|
from ..data_sources_interfaces import get_duckdb_interface_class, get_sqlite_interface_class
|
|
40
47
|
from ..dtype_codec import (
|
|
41
48
|
DATE,
|
|
@@ -1237,7 +1244,13 @@ class DataSource(BasePydanticModel, BaseObjectOrm):
|
|
|
1237
1244
|
raise NotImplementedError
|
|
1238
1245
|
|
|
1239
1246
|
|
|
1240
|
-
class MetaTable(
|
|
1247
|
+
class MetaTable(
|
|
1248
|
+
CurrentProjectEnvironmentResourceMixin,
|
|
1249
|
+
BasePydanticModel,
|
|
1250
|
+
LabelableObjectMixin,
|
|
1251
|
+
ShareableObjectMixin,
|
|
1252
|
+
BaseObjectOrm,
|
|
1253
|
+
):
|
|
1241
1254
|
ENDPOINT: ClassVar[str] = "meta-tables"
|
|
1242
1255
|
COLLECTION_CREATE_ROW_MODEL: ClassVar[type[ManagedMetaTableCollectionCreateRow]] = (
|
|
1243
1256
|
ManagedMetaTableCollectionCreateRow
|
|
@@ -1246,7 +1259,6 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
|
|
|
1246
1259
|
"identifier": ["in", "exact", "contains"],
|
|
1247
1260
|
"uid": ["in", "exact"],
|
|
1248
1261
|
"data_source__uid": ["in", "exact"],
|
|
1249
|
-
"organization_project_environment_uid": ["in", "exact"],
|
|
1250
1262
|
"namespace": ["exact", "contains", "in", "isnull"],
|
|
1251
1263
|
"management_mode": ["exact", "in"],
|
|
1252
1264
|
"provisioning_status": ["exact", "in"],
|
|
@@ -1261,8 +1273,6 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
|
|
|
1261
1273
|
"uid__in": "str",
|
|
1262
1274
|
"data_source__uid": "uid",
|
|
1263
1275
|
"data_source__uid__in": "uid",
|
|
1264
|
-
"organization_project_environment_uid": "uid",
|
|
1265
|
-
"organization_project_environment_uid__in": "uid",
|
|
1266
1276
|
"physical_schema": "str",
|
|
1267
1277
|
"physical_schema__in": "str",
|
|
1268
1278
|
"labels": "str",
|
|
@@ -1332,6 +1342,11 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
|
|
|
1332
1342
|
|
|
1333
1343
|
model_config = ConfigDict(populate_by_name=True)
|
|
1334
1344
|
|
|
1345
|
+
@classmethod
|
|
1346
|
+
def _sdk_owned_create_context(cls, operation: str) -> dict[str, str]:
|
|
1347
|
+
# MetaTable collection creation has its own managed project_context contract.
|
|
1348
|
+
return {}
|
|
1349
|
+
|
|
1335
1350
|
@model_validator(mode="before")
|
|
1336
1351
|
@classmethod
|
|
1337
1352
|
def _strip_legacy_storage_hash(cls, value: Any) -> Any:
|
|
@@ -1425,9 +1440,11 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
|
|
|
1425
1440
|
timeout: int | float | tuple[float, float] | None = None,
|
|
1426
1441
|
**filters: Any,
|
|
1427
1442
|
) -> list[MetaTable]:
|
|
1443
|
+
operation = f"{cls.__name__}.filter_by_body"
|
|
1444
|
+
cls._reject_sdk_context_overrides(filters, operation=operation)
|
|
1428
1445
|
response_json = cls._post_action(
|
|
1429
1446
|
"filter",
|
|
1430
|
-
filters,
|
|
1447
|
+
{**filters, **cls._sdk_owned_query_context(operation)},
|
|
1431
1448
|
timeout=timeout,
|
|
1432
1449
|
expected_statuses=(200,),
|
|
1433
1450
|
)
|
|
@@ -1472,7 +1489,12 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
|
|
|
1472
1489
|
**kwargs,
|
|
1473
1490
|
):
|
|
1474
1491
|
url = f"{type(self).get_object_url().rstrip('/')}/{self._public_uid()}/"
|
|
1475
|
-
|
|
1492
|
+
operation = f"{type(self).__name__}.patch"
|
|
1493
|
+
type(self)._reject_sdk_context_overrides(kwargs, operation=operation)
|
|
1494
|
+
payload = {
|
|
1495
|
+
"json": serialize_to_json(kwargs),
|
|
1496
|
+
"params": type(self)._sdk_owned_query_context(operation),
|
|
1497
|
+
}
|
|
1476
1498
|
response = make_request(
|
|
1477
1499
|
s=type(self).build_session(),
|
|
1478
1500
|
loaders=type(self).LOADERS,
|
|
@@ -1504,6 +1526,7 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
|
|
|
1504
1526
|
"full_delete_downstream_tables": full_delete_downstream_tables,
|
|
1505
1527
|
"delete_with_no_table": delete_with_no_table,
|
|
1506
1528
|
"override_protection": override_protection,
|
|
1529
|
+
**cls._sdk_owned_query_context(f"{cls.__name__}.delete"),
|
|
1507
1530
|
}
|
|
1508
1531
|
}
|
|
1509
1532
|
response = make_request(
|
|
@@ -1550,9 +1573,13 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
|
|
|
1550
1573
|
raise ValueError(
|
|
1551
1574
|
"project_context is SDK-controlled and cannot be supplied by the caller."
|
|
1552
1575
|
)
|
|
1576
|
+
if "organization_project_environment_uid" in unvalidated_payload:
|
|
1577
|
+
raise ValueError(
|
|
1578
|
+
"organization_project_environment_uid is SDK-controlled and cannot "
|
|
1579
|
+
"be supplied by the caller."
|
|
1580
|
+
)
|
|
1553
1581
|
payload = MetaTableRegistrationRequest.model_validate(unvalidated_payload)
|
|
1554
|
-
|
|
1555
|
-
payload = _with_current_metatable_project_context(payload)
|
|
1582
|
+
payload = _with_current_metatable_project_context(payload)
|
|
1556
1583
|
response_json = cls._post_action(
|
|
1557
1584
|
"register",
|
|
1558
1585
|
payload,
|
|
@@ -1823,6 +1850,8 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
|
|
|
1823
1850
|
q = (q or "").strip()
|
|
1824
1851
|
if not q:
|
|
1825
1852
|
raise ValueError("q is required")
|
|
1853
|
+
operation = f"{cls.__name__}.description_search"
|
|
1854
|
+
cls._reject_sdk_context_overrides(filters, operation=operation)
|
|
1826
1855
|
|
|
1827
1856
|
body = {
|
|
1828
1857
|
"q": q,
|
|
@@ -1838,6 +1867,7 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
|
|
|
1838
1867
|
|
|
1839
1868
|
if filters:
|
|
1840
1869
|
body.update(filters)
|
|
1870
|
+
body.update(cls._sdk_owned_query_context(operation))
|
|
1841
1871
|
|
|
1842
1872
|
payload = {"params": serialize_to_json(body)}
|
|
1843
1873
|
response = make_request(
|
|
@@ -1857,8 +1887,14 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
|
|
|
1857
1887
|
q = (q or "").strip()
|
|
1858
1888
|
if not q:
|
|
1859
1889
|
raise ValueError("q is required")
|
|
1890
|
+
operation = f"{cls.__name__}.column_search"
|
|
1891
|
+
cls._reject_sdk_context_overrides(filters, operation=operation)
|
|
1860
1892
|
|
|
1861
|
-
payload = {
|
|
1893
|
+
payload = {
|
|
1894
|
+
"params": serialize_to_json(
|
|
1895
|
+
{"q": q, **filters, **cls._sdk_owned_query_context(operation)}
|
|
1896
|
+
)
|
|
1897
|
+
}
|
|
1862
1898
|
response = make_request(
|
|
1863
1899
|
s=cls.build_session(),
|
|
1864
1900
|
loaders=cls.LOADERS,
|
|
@@ -3080,7 +3116,6 @@ class TimeIndexMetaTable(MetaTable):
|
|
|
3080
3116
|
"identifier": ["in", "exact", "contains"],
|
|
3081
3117
|
"uid": ["in", "exact"],
|
|
3082
3118
|
"data_source__uid": ["in", "exact"],
|
|
3083
|
-
"organization_project_environment_uid": ["in", "exact"],
|
|
3084
3119
|
"namespace": ["exact", "contains", "in", "isnull"],
|
|
3085
3120
|
"physical_schema": ["exact", "in"],
|
|
3086
3121
|
"physical_table_name": ["exact", "contains", "in"],
|
|
@@ -3091,8 +3126,6 @@ class TimeIndexMetaTable(MetaTable):
|
|
|
3091
3126
|
"uid__in": "uid",
|
|
3092
3127
|
"data_source__uid": "uid",
|
|
3093
3128
|
"data_source__uid__in": "uid",
|
|
3094
|
-
"organization_project_environment_uid": "uid",
|
|
3095
|
-
"organization_project_environment_uid__in": "uid",
|
|
3096
3129
|
"physical_schema": "str",
|
|
3097
3130
|
"physical_schema__in": "str",
|
|
3098
3131
|
"labels": "str",
|
|
@@ -3331,6 +3364,11 @@ class TimeIndexMetaTable(MetaTable):
|
|
|
3331
3364
|
raise ValueError(
|
|
3332
3365
|
"project_context is SDK-controlled and cannot be supplied by the caller."
|
|
3333
3366
|
)
|
|
3367
|
+
if "organization_project_environment_uid" in unvalidated_payload:
|
|
3368
|
+
raise ValueError(
|
|
3369
|
+
"organization_project_environment_uid is SDK-controlled and cannot "
|
|
3370
|
+
"be supplied by the caller."
|
|
3371
|
+
)
|
|
3334
3372
|
payload = TimeIndexMetaTableRegistrationRequest.model_validate(unvalidated_payload)
|
|
3335
3373
|
payload_json = _with_current_metatable_project_context(payload)
|
|
3336
3374
|
request_payload = {"json": serialize_to_json(payload_json)}
|
|
@@ -4706,6 +4744,10 @@ def _current_metatable_project_context() -> MetaTableProjectContextRequest:
|
|
|
4706
4744
|
return _metatable_project_context_from_resolution(get_project_runtime_context())
|
|
4707
4745
|
|
|
4708
4746
|
|
|
4747
|
+
def _current_metatable_environment_uid() -> str:
|
|
4748
|
+
return resolve_project_environment_uid("External MetaTable registration")
|
|
4749
|
+
|
|
4750
|
+
|
|
4709
4751
|
def _metatable_project_context_for_request() -> MetaTableProjectContextRequest | None:
|
|
4710
4752
|
return _current_metatable_project_context()
|
|
4711
4753
|
|
|
@@ -4716,7 +4758,15 @@ def _with_current_metatable_project_context(
|
|
|
4716
4758
|
payload_json = _payload_json(payload)
|
|
4717
4759
|
if "project_context" in payload_json:
|
|
4718
4760
|
raise ValueError("project_context is SDK-controlled and cannot be supplied by the caller.")
|
|
4761
|
+
if "organization_project_environment_uid" in payload_json:
|
|
4762
|
+
raise ValueError(
|
|
4763
|
+
"organization_project_environment_uid is SDK-controlled and cannot "
|
|
4764
|
+
"be supplied by the caller."
|
|
4765
|
+
)
|
|
4719
4766
|
if payload_json.get("management_mode") == "external_registered":
|
|
4767
|
+
payload_json["organization_project_environment_uid"] = (
|
|
4768
|
+
_current_metatable_environment_uid()
|
|
4769
|
+
)
|
|
4720
4770
|
return payload_json
|
|
4721
4771
|
project_context = _metatable_project_context_for_request()
|
|
4722
4772
|
if project_context is not None:
|
|
@@ -4730,13 +4780,23 @@ def _with_current_metatable_project_context_collection(
|
|
|
4730
4780
|
payload_rows = [dict(payload) for payload in payloads]
|
|
4731
4781
|
if any("project_context" in row for row in payload_rows):
|
|
4732
4782
|
raise ValueError("project_context is SDK-controlled and cannot be supplied by the caller.")
|
|
4783
|
+
if any("organization_project_environment_uid" in row for row in payload_rows):
|
|
4784
|
+
raise ValueError(
|
|
4785
|
+
"organization_project_environment_uid is SDK-controlled and cannot "
|
|
4786
|
+
"be supplied by the caller."
|
|
4787
|
+
)
|
|
4733
4788
|
managed_rows = [
|
|
4734
4789
|
row for row in payload_rows if row.get("management_mode") != "external_registered"
|
|
4735
4790
|
]
|
|
4736
|
-
|
|
4737
|
-
|
|
4791
|
+
external_rows = [
|
|
4792
|
+
row for row in payload_rows if row.get("management_mode") == "external_registered"
|
|
4793
|
+
]
|
|
4794
|
+
if external_rows:
|
|
4795
|
+
environment_uid = _current_metatable_environment_uid()
|
|
4796
|
+
for row in external_rows:
|
|
4797
|
+
row["organization_project_environment_uid"] = environment_uid
|
|
4738
4798
|
|
|
4739
|
-
project_context = _metatable_project_context_for_request()
|
|
4799
|
+
project_context = _metatable_project_context_for_request() if managed_rows else None
|
|
4740
4800
|
if project_context is not None:
|
|
4741
4801
|
current_project_context = project_context.model_dump(mode="json")
|
|
4742
4802
|
for row in managed_rows:
|