Files
wehub-resource-sync cddb07a176
docs / deploy (push) Has been cancelled
docs / changes (push) Has been cancelled
docs / check-and-build (push) Has been cancelled
build container image / cpu (push) Has been cancelled
build container image / cuda (push) Has been cancelled
build container image / rocm (push) Has been cancelled
frontend checks / frontend-checks (push) Has been cancelled
frontend tests / frontend-tests (push) Has been cancelled
lfs checks / lfs-check (push) Has been cancelled
python checks / python-checks (push) Has been cancelled
python tests / py3.12: macos-default (push) Has been cancelled
python tests / py3.11: windows-cpu (push) Has been cancelled
python tests / py3.12: windows-cpu (push) Has been cancelled
python tests / py3.11: linux-cpu (push) Has been cancelled
typegen checks / typegen-checks (push) Has been cancelled
uv lock checks / uv-lock-checks (push) Has been cancelled
openapi checks / openapi-checks (push) Has been cancelled
python tests / py3.11: macos-default (push) Has been cancelled
python tests / py3.12: linux-cpu (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:22:06 +08:00

116 lines
4.9 KiB
Python

"""Regression tests for the double-variant kwarg bug.
When override_fields contains a field (variant, repo_variant, prediction_type, etc.)
that is also computed and passed as an explicit kwarg to cls(), using .get() instead
of .pop() causes TypeError("got multiple values for keyword argument ...").
These tests verify that .pop() is used consistently, so override values don't conflict
with explicitly computed values.
"""
from pathlib import Path
from unittest.mock import MagicMock, patch
from invokeai.backend.model_manager.taxonomy import QwenImageVariantType
# Required fields for the Pydantic config model
_REQUIRED_FIELDS = {
"hash": "blake3:fakehash",
"path": "/fake/models/test-model",
"file_size": 1000,
"name": "test-model",
"description": "test",
"source": "test",
"source_type": "path",
"key": "test-key",
}
def _make_mock_dir(dirname: str = "test-model") -> MagicMock:
"""Create a mock ModelOnDisk for a Diffusers directory."""
mod = MagicMock()
mod.path = Path(f"/fake/models/{dirname}")
return mod
class TestDoubleVariantRegression:
"""Verify that override_fields with variant/repo_variant don't cause double-kwarg errors."""
@patch("invokeai.backend.model_manager.configs.main.raise_for_class_name")
@patch("invokeai.backend.model_manager.configs.main.raise_if_not_dir")
@patch("invokeai.backend.model_manager.configs.main.raise_for_override_fields")
def test_qwen_image_diffusers_with_variant_in_overrides(self, _rfo, _rid, _rfc):
"""Installing a Qwen Image Edit Diffusers model with variant in override_fields should not crash."""
from invokeai.backend.model_manager.configs.main import Main_Diffusers_QwenImage_Config
mod = _make_mock_dir("Qwen-Image-Edit-2511")
# Simulate what happens when a starter model provides variant
overrides = {
**_REQUIRED_FIELDS,
"variant": QwenImageVariantType.Edit,
}
from invokeai.backend.model_manager.configs.base import ModelRepoVariant
with patch.object(
Main_Diffusers_QwenImage_Config, "_get_repo_variant_or_raise", return_value=ModelRepoVariant("")
):
with patch.object(
Main_Diffusers_QwenImage_Config,
"_get_qwen_image_variant",
return_value=QwenImageVariantType.Edit,
):
# This would previously raise: TypeError("got multiple values for keyword argument 'variant'")
config = Main_Diffusers_QwenImage_Config.from_model_on_disk(mod, overrides)
assert config.variant == QwenImageVariantType.Edit
@patch("invokeai.backend.model_manager.configs.main.raise_for_class_name")
@patch("invokeai.backend.model_manager.configs.main.raise_if_not_dir")
@patch("invokeai.backend.model_manager.configs.main.raise_for_override_fields")
def test_qwen_image_diffusers_override_variant_takes_precedence(self, _rfo, _rid, _rfc):
"""An explicit variant override should take precedence over auto-detection."""
from invokeai.backend.model_manager.configs.base import ModelRepoVariant
from invokeai.backend.model_manager.configs.main import Main_Diffusers_QwenImage_Config
mod = _make_mock_dir("Qwen-Image-2512")
overrides = {
**_REQUIRED_FIELDS,
"variant": QwenImageVariantType.Edit, # explicitly override to Edit
}
with patch.object(
Main_Diffusers_QwenImage_Config, "_get_repo_variant_or_raise", return_value=ModelRepoVariant("")
):
with patch.object(
Main_Diffusers_QwenImage_Config,
"_get_qwen_image_variant",
return_value=QwenImageVariantType.Generate, # auto-detect says Generate
):
config = Main_Diffusers_QwenImage_Config.from_model_on_disk(mod, overrides)
# Override should win over auto-detection
assert config.variant == QwenImageVariantType.Edit
@patch("invokeai.backend.model_manager.configs.main._has_qwen_image_keys", return_value=True)
@patch("invokeai.backend.model_manager.configs.main._has_ggml_tensors", return_value=True)
@patch("invokeai.backend.model_manager.configs.main.raise_if_not_file")
@patch("invokeai.backend.model_manager.configs.main.raise_for_override_fields")
def test_qwen_image_gguf_with_variant_in_overrides(self, _rfo, _rif, _hgt, _hqk):
"""Installing a Qwen Image Edit GGUF with variant in override_fields should not crash."""
from invokeai.backend.model_manager.configs.main import Main_GGUF_QwenImage_Config
mod = MagicMock()
mod.path = Path("/fake/models/qwen-image-edit-2511-Q4_K_M.gguf")
mod.load_state_dict.return_value = {}
overrides = {
**_REQUIRED_FIELDS,
"variant": QwenImageVariantType.Edit,
}
config = Main_GGUF_QwenImage_Config.from_model_on_disk(mod, overrides)
assert config.variant == QwenImageVariantType.Edit