mainsequence 4.2.14__tar.gz → 4.2.16__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.14/mainsequence.egg-info → mainsequence-4.2.16}/PKG-INFO +1 -1
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/migrations.py +161 -34
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/metatables/core.py +320 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/migrations.py +201 -13
- {mainsequence-4.2.14 → mainsequence-4.2.16/mainsequence.egg-info}/PKG-INFO +1 -1
- {mainsequence-4.2.14 → mainsequence-4.2.16}/pyproject.toml +1 -1
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_cli_migrations.py +107 -11
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_meta_table_migrations.py +248 -15
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_meta_tables_client_models.py +132 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/LICENSE +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/README.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/a2a_communication/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/command_center/adapter_from_api/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/command_center/app_components/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/command_center/connections/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/command_center/workspace_design/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/ms-markets/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/agent_scaffold/skills/project_to_agent/SKILL.md +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/__init__.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/__main__.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/bootstrap.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/api.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/cli.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/config.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/project_status.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/cli/ui.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/__init__.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/agent_runtime_models.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/base.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/client.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/command_center/__init__.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/command_center/app_component.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/command_center/connections.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/command_center/data_models.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/command_center/workspace.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/command_center/workspace_snapshot.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/compute_validation.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/dtype_codec.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/fastapi/__init__.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/fastapi/auth.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/metatables/__init__.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/models_foundry.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/models_helpers.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/models_user.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/client/utils.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/defaults.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/logconf.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/__init__.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/__main__.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/data_nodes/data_nodes.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/data_nodes/models.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/data_nodes/persist_managers.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/data_nodes/run_operations.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/future_registry.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/hashing.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence.egg-info/SOURCES.txt +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence.egg-info/requires.txt +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/setup.cfg +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_auth_precedence.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_build_operations_hashing.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_cli.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_client.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_command_center_app_component_models.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_command_center_data_models.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_command_center_models.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_data_access_mixin_dimension_audit.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_data_node_storage_dimension_queries.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_data_node_update_flow.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_dependency_extras.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_duckdb_interface_dimensions.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_filter_normalization.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_logconf.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_pod_project_resolution.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_project_batch_jobs_from_file.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_run_configuration.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_secret_client_model.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_source_table_configuration.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_sqlite_interface_dimensions.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_update_runner_uid_runtime.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_update_statistics.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_update_uid_guards.py +0 -0
- {mainsequence-4.2.14 → mainsequence-4.2.16}/tests/test_workspace_snapshot.py +0 -0
|
@@ -2,9 +2,11 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import dataclasses
|
|
4
4
|
import json
|
|
5
|
+
import logging
|
|
5
6
|
import re
|
|
6
7
|
import sys
|
|
7
8
|
from collections.abc import Mapping, Sequence
|
|
9
|
+
from contextlib import contextmanager
|
|
8
10
|
from typing import Any
|
|
9
11
|
|
|
10
12
|
import click
|
|
@@ -23,6 +25,8 @@ from mainsequence.meta_tables.migrations import (
|
|
|
23
25
|
migrations = typer.Typer(help="Alembic-owned MetaTable migration commands")
|
|
24
26
|
REGISTER_ENDPOINT = "/orm/api/ts_manager/meta_table/register/"
|
|
25
27
|
RESERVE_MANAGED_ENDPOINT = "/orm/api/ts_manager/meta_table/reserve-managed/"
|
|
28
|
+
FINALIZE_MANAGED_ENDPOINT = "/orm/api/ts_manager/meta_table/finalize-managed/"
|
|
29
|
+
ALEMBIC_PROVIDER_RESET_ENDPOINT = "/orm/api/ts_manager/meta_table/alembic-provider-reset/"
|
|
26
30
|
|
|
27
31
|
|
|
28
32
|
class _AlembicOutput:
|
|
@@ -44,6 +48,46 @@ class _AlembicOutput:
|
|
|
44
48
|
return any(chunk.strip() for chunk in self._chunks)
|
|
45
49
|
|
|
46
50
|
|
|
51
|
+
class _AlembicLogHandler(logging.Handler):
|
|
52
|
+
def emit(self, record: logging.LogRecord) -> None:
|
|
53
|
+
try:
|
|
54
|
+
message = self.format(record)
|
|
55
|
+
except Exception:
|
|
56
|
+
self.handleError(record)
|
|
57
|
+
return
|
|
58
|
+
print(message, file=sys.stderr, flush=True)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@contextmanager
|
|
62
|
+
def _forward_alembic_logging():
|
|
63
|
+
logger_names = {"alembic"}
|
|
64
|
+
logger_names.update(
|
|
65
|
+
name
|
|
66
|
+
for name in logging.Logger.manager.loggerDict
|
|
67
|
+
if name == "alembic" or name.startswith("alembic.")
|
|
68
|
+
)
|
|
69
|
+
loggers = [logging.getLogger(name) for name in logger_names]
|
|
70
|
+
previous_state = [(logger, logger.level, logger.propagate) for logger in loggers]
|
|
71
|
+
handler = _AlembicLogHandler()
|
|
72
|
+
handler.setLevel(logging.DEBUG)
|
|
73
|
+
handler.setFormatter(
|
|
74
|
+
logging.Formatter("[alembic] %(levelname)s %(name)s: %(message)s")
|
|
75
|
+
)
|
|
76
|
+
root_logger = logging.getLogger("alembic")
|
|
77
|
+
root_logger.addHandler(handler)
|
|
78
|
+
for logger in loggers:
|
|
79
|
+
logger.setLevel(logging.DEBUG)
|
|
80
|
+
logger.propagate = True
|
|
81
|
+
root_logger.propagate = False
|
|
82
|
+
try:
|
|
83
|
+
yield
|
|
84
|
+
finally:
|
|
85
|
+
root_logger.removeHandler(handler)
|
|
86
|
+
for logger, level, propagate in previous_state:
|
|
87
|
+
logger.setLevel(level)
|
|
88
|
+
logger.propagate = propagate
|
|
89
|
+
|
|
90
|
+
|
|
47
91
|
def _emit_status(message: str) -> None:
|
|
48
92
|
print(f"[mainsequence migrations] {message}", file=sys.stderr, flush=True)
|
|
49
93
|
|
|
@@ -234,6 +278,17 @@ def _emit_metatable_reservation(model: type[Any], item: Any) -> None:
|
|
|
234
278
|
)
|
|
235
279
|
|
|
236
280
|
|
|
281
|
+
def _emit_metatable_finalization(model: type[Any], item: Any) -> None:
|
|
282
|
+
_emit_progress(
|
|
283
|
+
_metatable_message(
|
|
284
|
+
endpoint=FINALIZE_MANAGED_ENDPOINT,
|
|
285
|
+
action="finalized",
|
|
286
|
+
model=model,
|
|
287
|
+
item=item,
|
|
288
|
+
),
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
|
|
237
292
|
def _prepare_alembic_config(
|
|
238
293
|
migration: AlembicMetaTableMigration,
|
|
239
294
|
*,
|
|
@@ -301,15 +356,16 @@ def _next_sequential_revision_id(
|
|
|
301
356
|
_emit_status("Imported Alembic ScriptDirectory.")
|
|
302
357
|
|
|
303
358
|
_emit_status("Scanning Alembic revision directory for next sequential id...")
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
359
|
+
with _forward_alembic_logging():
|
|
360
|
+
script = ScriptDirectory.from_config(
|
|
361
|
+
alembic_config_for_provider(
|
|
362
|
+
migration,
|
|
363
|
+
sqlalchemy_url="postgresql://",
|
|
364
|
+
stdout=alembic_output,
|
|
365
|
+
output_buffer=alembic_output,
|
|
366
|
+
)
|
|
310
367
|
)
|
|
311
|
-
|
|
312
|
-
heads = list(script.get_heads())
|
|
368
|
+
heads = list(script.get_heads())
|
|
313
369
|
if len(heads) > 1:
|
|
314
370
|
raise typer.BadParameter(
|
|
315
371
|
"Sequential revision IDs require a single Alembic head. Pass --rev-id "
|
|
@@ -324,10 +380,11 @@ def _next_sequential_revision_id(
|
|
|
324
380
|
)
|
|
325
381
|
|
|
326
382
|
numeric_revisions: list[int] = []
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
383
|
+
with _forward_alembic_logging():
|
|
384
|
+
for revision in script.walk_revisions():
|
|
385
|
+
revision_id = str(revision.revision)
|
|
386
|
+
if re.fullmatch(r"\d{4,}", revision_id):
|
|
387
|
+
numeric_revisions.append(int(revision_id))
|
|
331
388
|
next_revision_id = f"{max(numeric_revisions, default=0) + 1:04d}"
|
|
332
389
|
_emit_status(f"Next Alembic revision id is {next_revision_id}.")
|
|
333
390
|
return next_revision_id
|
|
@@ -356,7 +413,8 @@ def current(
|
|
|
356
413
|
alembic_output=alembic_output,
|
|
357
414
|
)
|
|
358
415
|
_emit_status("Starting Alembic current now...")
|
|
359
|
-
|
|
416
|
+
with _forward_alembic_logging():
|
|
417
|
+
command.current(config, verbose=verbose)
|
|
360
418
|
if not alembic_output.has_visible_output:
|
|
361
419
|
_emit_status(
|
|
362
420
|
"Alembic current produced no revision output. The version table is "
|
|
@@ -406,13 +464,14 @@ def revision(
|
|
|
406
464
|
alembic_output=alembic_output,
|
|
407
465
|
)
|
|
408
466
|
_emit_status(f"Starting Alembic revision now rev_id={resolved_rev_id}...")
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
467
|
+
with _forward_alembic_logging():
|
|
468
|
+
script = command.revision(
|
|
469
|
+
config,
|
|
470
|
+
message=resolved_message,
|
|
471
|
+
autogenerate=autogenerate,
|
|
472
|
+
rev_id=resolved_rev_id,
|
|
473
|
+
head=head,
|
|
474
|
+
)
|
|
416
475
|
_emit_status("Alembic revision finished.")
|
|
417
476
|
_emit(
|
|
418
477
|
{
|
|
@@ -438,7 +497,7 @@ def upgrade(
|
|
|
438
497
|
ttl_seconds: int = typer.Option(900, "--ttl-seconds", min=1),
|
|
439
498
|
json_output: bool = typer.Option(False, "--json", help="Emit JSON."),
|
|
440
499
|
) -> None:
|
|
441
|
-
"""Run Alembic upgrade directly and
|
|
500
|
+
"""Run Alembic upgrade directly and finalize reserved MetaTables."""
|
|
442
501
|
|
|
443
502
|
command = _load_alembic_command("upgrade")
|
|
444
503
|
migration = _load_migration(provider)
|
|
@@ -450,13 +509,17 @@ def upgrade(
|
|
|
450
509
|
alembic_output=alembic_output,
|
|
451
510
|
)
|
|
452
511
|
_emit_status(f"Starting Alembic upgrade now target={target_revision}...")
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
512
|
+
with _forward_alembic_logging():
|
|
513
|
+
command.upgrade(config, target_revision)
|
|
514
|
+
_emit_status("Finalizing MetaTable catalog after upgrade...")
|
|
515
|
+
finalize_response = migration.finalize_metatable_catalog(
|
|
516
|
+
prepared=prepared,
|
|
517
|
+
alembic_revision=target_revision,
|
|
456
518
|
timeout=timeout,
|
|
457
|
-
|
|
519
|
+
on_metatable_finalized=_emit_metatable_finalization,
|
|
520
|
+
on_metatable_finalize_status=_emit_status,
|
|
458
521
|
)
|
|
459
|
-
_emit_status("MetaTable catalog
|
|
522
|
+
_emit_status("MetaTable catalog finalization finished.")
|
|
460
523
|
_emit(
|
|
461
524
|
{
|
|
462
525
|
"ok": True,
|
|
@@ -464,7 +527,10 @@ def upgrade(
|
|
|
464
527
|
"package": migration.package,
|
|
465
528
|
"migration_namespace": migration.migration_namespace,
|
|
466
529
|
"meta_table_uids": prepared.meta_table_uids,
|
|
467
|
-
"
|
|
530
|
+
"finalized_count": finalize_response.finalized_count,
|
|
531
|
+
"active_count": finalize_response.active_count,
|
|
532
|
+
"reserved_count": finalize_response.reserved_count,
|
|
533
|
+
"failed_count": finalize_response.failed_count,
|
|
468
534
|
},
|
|
469
535
|
json_output=json_output,
|
|
470
536
|
)
|
|
@@ -482,7 +548,7 @@ def downgrade(
|
|
|
482
548
|
ttl_seconds: int = typer.Option(900, "--ttl-seconds", min=1),
|
|
483
549
|
json_output: bool = typer.Option(False, "--json", help="Emit JSON."),
|
|
484
550
|
) -> None:
|
|
485
|
-
"""Run Alembic downgrade directly and
|
|
551
|
+
"""Run Alembic downgrade directly and finalize reserved MetaTables."""
|
|
486
552
|
|
|
487
553
|
command = _load_alembic_command("downgrade")
|
|
488
554
|
migration = _load_migration(provider)
|
|
@@ -494,13 +560,17 @@ def downgrade(
|
|
|
494
560
|
alembic_output=alembic_output,
|
|
495
561
|
)
|
|
496
562
|
_emit_status(f"Starting Alembic downgrade now target={target_revision}...")
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
563
|
+
with _forward_alembic_logging():
|
|
564
|
+
command.downgrade(config, target_revision)
|
|
565
|
+
_emit_status("Finalizing MetaTable catalog after downgrade...")
|
|
566
|
+
finalize_response = migration.finalize_metatable_catalog(
|
|
567
|
+
prepared=prepared,
|
|
568
|
+
alembic_revision=target_revision,
|
|
500
569
|
timeout=timeout,
|
|
501
|
-
|
|
570
|
+
on_metatable_finalized=_emit_metatable_finalization,
|
|
571
|
+
on_metatable_finalize_status=_emit_status,
|
|
502
572
|
)
|
|
503
|
-
_emit_status("MetaTable catalog
|
|
573
|
+
_emit_status("MetaTable catalog finalization finished.")
|
|
504
574
|
_emit(
|
|
505
575
|
{
|
|
506
576
|
"ok": True,
|
|
@@ -508,7 +578,64 @@ def downgrade(
|
|
|
508
578
|
"package": migration.package,
|
|
509
579
|
"migration_namespace": migration.migration_namespace,
|
|
510
580
|
"meta_table_uids": prepared.meta_table_uids,
|
|
511
|
-
"
|
|
581
|
+
"finalized_count": finalize_response.finalized_count,
|
|
582
|
+
"active_count": finalize_response.active_count,
|
|
583
|
+
"reserved_count": finalize_response.reserved_count,
|
|
584
|
+
"failed_count": finalize_response.failed_count,
|
|
512
585
|
},
|
|
513
586
|
json_output=json_output,
|
|
514
587
|
)
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
@migrations.command("reset")
|
|
591
|
+
def reset(
|
|
592
|
+
provider: str | None = typer.Option(
|
|
593
|
+
None,
|
|
594
|
+
"--provider",
|
|
595
|
+
help="Migration provider reference, for example msm.migrations:migration.",
|
|
596
|
+
),
|
|
597
|
+
confirm_reset: bool = typer.Option(
|
|
598
|
+
False,
|
|
599
|
+
"--confirm-reset",
|
|
600
|
+
help="Required confirmation for destructive provider-scoped reset.",
|
|
601
|
+
),
|
|
602
|
+
drop_physical_tables: bool = typer.Option(
|
|
603
|
+
True,
|
|
604
|
+
"--drop-physical-tables/--keep-physical-tables",
|
|
605
|
+
help="Drop provider physical tables during reset.",
|
|
606
|
+
),
|
|
607
|
+
clear_alembic_version_table: bool = typer.Option(
|
|
608
|
+
True,
|
|
609
|
+
"--clear-alembic-version-table/--keep-alembic-version-table",
|
|
610
|
+
help="Clear the provider Alembic version table during reset.",
|
|
611
|
+
),
|
|
612
|
+
include_reserved: bool = typer.Option(
|
|
613
|
+
True,
|
|
614
|
+
"--include-reserved/--active-only",
|
|
615
|
+
help="Include already-reserved provider MetaTables in reset results.",
|
|
616
|
+
),
|
|
617
|
+
timeout: float | None = typer.Option(None, "--timeout"),
|
|
618
|
+
json_output: bool = typer.Option(False, "--json", help="Emit JSON."),
|
|
619
|
+
) -> None:
|
|
620
|
+
"""Reset an Alembic-managed provider catalog/physical state."""
|
|
621
|
+
|
|
622
|
+
if not confirm_reset:
|
|
623
|
+
raise typer.BadParameter(
|
|
624
|
+
"Pass --confirm-reset to call the destructive provider reset endpoint.",
|
|
625
|
+
param_hint="--confirm-reset",
|
|
626
|
+
)
|
|
627
|
+
migration = _load_migration(provider)
|
|
628
|
+
_emit_status(
|
|
629
|
+
"Calling provider reset endpoint "
|
|
630
|
+
f"{ALEMBIC_PROVIDER_RESET_ENDPOINT} provider={migration.migration_provider_key}..."
|
|
631
|
+
)
|
|
632
|
+
response = migration.reset_alembic_provider(
|
|
633
|
+
confirm_reset=True,
|
|
634
|
+
drop_physical_tables=drop_physical_tables,
|
|
635
|
+
clear_alembic_version_table=clear_alembic_version_table,
|
|
636
|
+
include_reserved=include_reserved,
|
|
637
|
+
timeout=timeout,
|
|
638
|
+
on_reset_status=_emit_status,
|
|
639
|
+
)
|
|
640
|
+
_emit_status("Alembic provider reset finished.")
|
|
641
|
+
_emit(response, json_output=json_output)
|