Release v0.1.6
This commit is contained in:
@@ -10,8 +10,11 @@ from alembic.runtime.migration import MigrationContext
|
||||
from sqlalchemy import create_engine, inspect, text
|
||||
|
||||
from govoplan_core.core.migrations import MigrationMetadataPlan, migration_metadata_plan
|
||||
from govoplan_core.core.module_management import load_startup_enabled_modules, startup_candidate_module_ids
|
||||
from govoplan_core.db.session import configure_database
|
||||
from govoplan_core.server.default_config import get_server_config
|
||||
from govoplan_core.server.registry import build_platform_registry
|
||||
from govoplan_core.server.config import ManifestFactory
|
||||
from govoplan_core.server.registry import available_module_manifests, build_platform_registry
|
||||
from govoplan_core.settings import settings
|
||||
|
||||
# Historic development databases could be created partly through Alembic and
|
||||
@@ -133,11 +136,32 @@ class MigrationResult:
|
||||
current_revision: str | None
|
||||
|
||||
|
||||
def registered_module_migration_plan() -> MigrationMetadataPlan:
|
||||
def registered_module_migration_plan(
|
||||
database_url: str | None = None,
|
||||
*,
|
||||
enabled_modules: tuple[str, ...] | list[str] | None = None,
|
||||
manifest_factories: tuple[ManifestFactory, ...] = (),
|
||||
) -> MigrationMetadataPlan:
|
||||
server_config = get_server_config()
|
||||
active_database_url = database_url or settings.database_url
|
||||
if active_database_url:
|
||||
configure_database(active_database_url)
|
||||
active_manifest_factories = manifest_factories or tuple(server_config.manifest_factories)
|
||||
raw_enabled_modules = tuple(enabled_modules) if enabled_modules is not None else load_startup_enabled_modules(server_config.enabled_modules)
|
||||
candidate_modules = startup_candidate_module_ids(server_config.enabled_modules, raw_enabled_modules)
|
||||
available_modules = available_module_manifests(
|
||||
active_manifest_factories,
|
||||
enabled_modules=candidate_modules,
|
||||
ignore_load_errors=True,
|
||||
)
|
||||
active_enabled_modules = (
|
||||
tuple(enabled_modules)
|
||||
if enabled_modules is not None
|
||||
else load_startup_enabled_modules(server_config.enabled_modules, available=available_modules)
|
||||
)
|
||||
registry = build_platform_registry(
|
||||
server_config.enabled_modules,
|
||||
manifest_factories=server_config.manifest_factories,
|
||||
active_enabled_modules,
|
||||
manifest_factories=active_manifest_factories,
|
||||
)
|
||||
return migration_metadata_plan(registry)
|
||||
|
||||
@@ -146,18 +170,32 @@ def _repo_root() -> Path:
|
||||
return Path(__file__).resolve().parents[3]
|
||||
|
||||
|
||||
def alembic_config(*, database_url: str | None = None) -> Config:
|
||||
def alembic_config(
|
||||
*,
|
||||
database_url: str | None = None,
|
||||
enabled_modules: tuple[str, ...] | list[str] | None = None,
|
||||
manifest_factories: tuple[ManifestFactory, ...] = (),
|
||||
) -> Config:
|
||||
root = _repo_root()
|
||||
config = Config(str(root / "alembic.ini"))
|
||||
config.set_main_option("script_location", str(root / "alembic"))
|
||||
|
||||
plan = registered_module_migration_plan()
|
||||
active_database_url = database_url or settings.database_url
|
||||
plan = registered_module_migration_plan(
|
||||
active_database_url,
|
||||
enabled_modules=enabled_modules,
|
||||
manifest_factories=manifest_factories,
|
||||
)
|
||||
version_locations = [str(root / "alembic" / "versions")]
|
||||
version_locations.extend(location for location in plan.script_locations if location)
|
||||
config.set_main_option("version_locations", os.pathsep.join(dict.fromkeys(version_locations)))
|
||||
config.set_main_option("version_path_separator", "os")
|
||||
|
||||
config.attributes["database_url"] = database_url or settings.database_url
|
||||
config.attributes["database_url"] = active_database_url
|
||||
if enabled_modules is not None:
|
||||
config.attributes["enabled_modules"] = tuple(enabled_modules)
|
||||
if manifest_factories:
|
||||
config.attributes["manifest_factories"] = tuple(manifest_factories)
|
||||
return config
|
||||
|
||||
|
||||
@@ -166,7 +204,12 @@ def database_revision(database_url: str | None = None) -> str | None:
|
||||
engine = create_engine(url)
|
||||
try:
|
||||
with engine.connect() as connection:
|
||||
return MigrationContext.configure(connection).get_current_revision()
|
||||
heads = MigrationContext.configure(connection).get_current_heads()
|
||||
if not heads:
|
||||
return None
|
||||
if len(heads) == 1:
|
||||
return heads[0]
|
||||
return ",".join(sorted(heads))
|
||||
finally:
|
||||
engine.dispose()
|
||||
|
||||
@@ -227,7 +270,9 @@ def reconcile_legacy_create_all_schema(database_url: str | None = None) -> str |
|
||||
engine = create_engine(url)
|
||||
try:
|
||||
with engine.connect() as connection:
|
||||
current = MigrationContext.configure(connection).get_current_revision()
|
||||
heads = MigrationContext.configure(connection).get_current_heads()
|
||||
current = heads[0] if len(heads) == 1 else None
|
||||
has_no_revision = len(heads) == 0
|
||||
schema = inspect(connection)
|
||||
tables = set(schema.get_table_names())
|
||||
|
||||
@@ -259,10 +304,10 @@ def reconcile_legacy_create_all_schema(database_url: str | None = None) -> str |
|
||||
# run normally.
|
||||
_backfill_user_lock_state_for_create_all_schema(url)
|
||||
target = REVISION_HIERARCHICAL_SETTINGS
|
||||
elif current is None and has_create_all_hierarchical_schema:
|
||||
elif has_no_revision and has_create_all_hierarchical_schema:
|
||||
_backfill_user_lock_state_for_create_all_schema(url)
|
||||
target = REVISION_HIERARCHICAL_SETTINGS
|
||||
elif current is None and has_file_storage and has_file_folders:
|
||||
elif has_no_revision and has_file_storage and has_file_folders:
|
||||
# This is the other create_all-only development shape. The strict
|
||||
# column checks above ensure that we only stamp a complete known schema.
|
||||
target = REVISION_FILE_FOLDERS
|
||||
@@ -278,11 +323,20 @@ def migrate_database(
|
||||
*,
|
||||
database_url: str | None = None,
|
||||
reconcile_legacy_schema: bool = True,
|
||||
enabled_modules: tuple[str, ...] | list[str] | None = None,
|
||||
manifest_factories: tuple[ManifestFactory, ...] = (),
|
||||
) -> MigrationResult:
|
||||
url = database_url or settings.database_url
|
||||
previous = database_revision(url)
|
||||
reconciled = reconcile_legacy_create_all_schema(url) if reconcile_legacy_schema else None
|
||||
command.upgrade(alembic_config(database_url=url), "head")
|
||||
command.upgrade(
|
||||
alembic_config(
|
||||
database_url=url,
|
||||
enabled_modules=enabled_modules,
|
||||
manifest_factories=manifest_factories,
|
||||
),
|
||||
"heads",
|
||||
)
|
||||
current = database_revision(url)
|
||||
return MigrationResult(
|
||||
previous_revision=previous,
|
||||
|
||||
Reference in New Issue
Block a user