mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
check for strictly contiguous from_version->to_version ranges
This commit is contained in:
parent
ab9ebef345
commit
6eaed9a9cb
@ -444,7 +444,7 @@ def get_config() -> InvokeAIAppConfig:
|
||||
####################################################
|
||||
|
||||
|
||||
@ConfigMigrator.register(from_version="0.0.0", to_version="4.0.0")
|
||||
@ConfigMigrator.register(from_version="3.0.0", to_version="4.0.0")
|
||||
def migrate_1(config_dict: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Migrate a v3 config dictionary to a current config object.
|
||||
|
||||
|
@ -48,11 +48,14 @@ class ConfigMigrator:
|
||||
return decorator
|
||||
|
||||
@staticmethod
|
||||
def _check_for_overlaps(migrations: List[MigrationEntry]) -> None:
|
||||
current_version = Version("0.0.0")
|
||||
def _check_for_discontinuities(migrations: List[MigrationEntry]) -> None:
|
||||
current_version = Version("3.0.0")
|
||||
for m in migrations:
|
||||
if current_version > m.from_version:
|
||||
raise ValueError(f"Version range overlap detected while processing function {m.function.__name__}")
|
||||
if current_version != m.from_version:
|
||||
raise ValueError(
|
||||
f"Migration functions are not continuous. Expected from_version={current_version} but got from_version={m.from_version}, for migration function {m.function.__name__}"
|
||||
)
|
||||
current_version = m.to_version
|
||||
|
||||
@classmethod
|
||||
def migrate(cls, config_dict: AppConfigDict) -> AppConfigDict:
|
||||
@ -68,9 +71,9 @@ class ConfigMigrator:
|
||||
ValueError exception.
|
||||
"""
|
||||
# Sort migrations by version number and raise a ValueError if
|
||||
# any version range overlaps are detected. Discontinuities are ok
|
||||
# any version range overlaps are detected.
|
||||
sorted_migrations = sorted(cls._migrations, key=lambda x: x.from_version)
|
||||
cls._check_for_overlaps(sorted_migrations)
|
||||
cls._check_for_discontinuities(sorted_migrations)
|
||||
|
||||
if "InvokeAI" in config_dict:
|
||||
version = Version("3.0.0")
|
||||
@ -78,7 +81,7 @@ class ConfigMigrator:
|
||||
version = Version(config_dict["schema_version"])
|
||||
|
||||
for migration in sorted_migrations:
|
||||
if version >= migration.from_version and version < migration.to_version:
|
||||
if version == migration.from_version and version < migration.to_version:
|
||||
config_dict = migration.function(config_dict)
|
||||
version = migration.to_version
|
||||
|
||||
|
@ -4,6 +4,7 @@ from typing import Any
|
||||
|
||||
import pytest
|
||||
from omegaconf import OmegaConf
|
||||
from packaging.version import Version
|
||||
from pydantic import ValidationError
|
||||
|
||||
from invokeai.app.services.config.config_default import (
|
||||
@ -18,12 +19,13 @@ invalid_v4_0_1_config = """
|
||||
schema_version: 4.0.1
|
||||
|
||||
host: "192.168.1.1"
|
||||
port: 8080
|
||||
port: "ice cream"
|
||||
"""
|
||||
|
||||
v4_config = """
|
||||
schema_version: 4.0.0
|
||||
|
||||
precision: autocast
|
||||
host: "192.168.1.1"
|
||||
port: 8080
|
||||
"""
|
||||
@ -141,6 +143,16 @@ def test_migrate_v3_backup(tmp_path: Path, patch_rootdir: None):
|
||||
assert temp_config_file.with_suffix(".yaml.bak").read_text() == v3_config
|
||||
|
||||
|
||||
def test_migrate_v4(tmp_path: Path, patch_rootdir: None):
|
||||
"""Test migration from 4.0.0 to 4.0.1"""
|
||||
temp_config_file = tmp_path / "temp_invokeai.yaml"
|
||||
temp_config_file.write_text(v4_config)
|
||||
|
||||
conf = load_and_migrate_config(temp_config_file)
|
||||
assert Version(conf.schema_version) >= Version("4.0.1")
|
||||
assert conf.precision == "auto" # we expect 'autocast' to be replaced with 'auto' during 4.0.1 migration
|
||||
|
||||
|
||||
def test_failed_migrate_backup(tmp_path: Path, patch_rootdir: None):
|
||||
"""Test the failed migration of the config file."""
|
||||
temp_config_file = tmp_path / "temp_invokeai.yaml"
|
||||
@ -162,13 +174,15 @@ def test_bails_on_invalid_config(tmp_path: Path, patch_rootdir: None):
|
||||
with pytest.raises(AssertionError):
|
||||
load_and_migrate_config(temp_config_file)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("config_content", [invalid_v5_config, invalid_v4_0_1_config])
|
||||
def test_bails_on_config_with_unsupported_version(tmp_path: Path, patch_rootdir: None, config_content: str):
|
||||
"""Test reading configuration from a file."""
|
||||
temp_config_file = tmp_path / "temp_invokeai.yaml"
|
||||
temp_config_file.write_text(config_content)
|
||||
|
||||
with pytest.raises(RuntimeError, match="Invalid schema version"):
|
||||
# with pytest.raises(RuntimeError, match="Invalid schema version"):
|
||||
with pytest.raises(RuntimeError):
|
||||
load_and_migrate_config(temp_config_file)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user