mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-04-10 12:52:15 -03:00
feat(settings): skip previously downloaded model versions
This commit is contained in:
@@ -341,6 +341,10 @@
|
||||
"saveFailed": "Ausgeschlossene Basismodelle konnten nicht gespeichert werden: {message}"
|
||||
}
|
||||
},
|
||||
"skipPreviouslyDownloadedModelVersions": {
|
||||
"label": "Bereits heruntergeladene Modellversionen überspringen",
|
||||
"help": "Wenn aktiviert, überspringt LoRA Manager den Download einer Modellversion, wenn der Download-Verlaufsdienst diese spezifische Version als bereits heruntergeladen erfasst hat. Gilt für alle Download-Abläufe."
|
||||
},
|
||||
"layoutSettings": {
|
||||
"displayDensity": "Anzeige-Dichte",
|
||||
"displayDensityOptions": {
|
||||
@@ -827,7 +831,7 @@
|
||||
},
|
||||
"contextMenu": {
|
||||
"moveToOtherTypeFolder": "In {otherType}-Ordner verschieben",
|
||||
"sendToWorkflow": "[TODO: Translate] Send to Workflow"
|
||||
"sendToWorkflow": "An Workflow senden"
|
||||
}
|
||||
},
|
||||
"embeddings": {
|
||||
|
||||
@@ -325,7 +325,7 @@
|
||||
},
|
||||
"downloadSkipBaseModels": {
|
||||
"label": "Skip downloads for base models",
|
||||
"help": "When a model version uses one of these base models, LoRA Manager will skip the download before any file transfer starts. Applies to all download flows. Only supported base models can be selected here.",
|
||||
"help": "When enabled, versions using the selected base models will be skipped.",
|
||||
"searchPlaceholder": "Filter base models...",
|
||||
"empty": "No base models match the current search.",
|
||||
"summary": {
|
||||
@@ -341,6 +341,10 @@
|
||||
"saveFailed": "Unable to save excluded base models: {message}"
|
||||
}
|
||||
},
|
||||
"skipPreviouslyDownloadedModelVersions": {
|
||||
"label": "Skip previously downloaded model versions",
|
||||
"help": "When enabled, versions downloaded before will be skipped."
|
||||
},
|
||||
"layoutSettings": {
|
||||
"displayDensity": "Display Density",
|
||||
"displayDensityOptions": {
|
||||
|
||||
@@ -341,6 +341,10 @@
|
||||
"saveFailed": "No se pudieron guardar los modelos base excluidos: {message}"
|
||||
}
|
||||
},
|
||||
"skipPreviouslyDownloadedModelVersions": {
|
||||
"label": "Omitir versiones de modelos previamente descargadas",
|
||||
"help": "Cuando está habilitado, LoRA Manager omitirá la descarga de una versión de modelo si el servicio de historial de descargas registra esa versión exacta como ya descargada. Aplica a todos los flujos de descarga."
|
||||
},
|
||||
"layoutSettings": {
|
||||
"displayDensity": "Densidad de visualización",
|
||||
"displayDensityOptions": {
|
||||
@@ -827,7 +831,7 @@
|
||||
},
|
||||
"contextMenu": {
|
||||
"moveToOtherTypeFolder": "Mover a la carpeta {otherType}",
|
||||
"sendToWorkflow": "[TODO: Translate] Send to Workflow"
|
||||
"sendToWorkflow": "Enviar al flujo de trabajo"
|
||||
}
|
||||
},
|
||||
"embeddings": {
|
||||
|
||||
@@ -341,6 +341,10 @@
|
||||
"saveFailed": "Impossible d’enregistrer les modèles de base exclus : {message}"
|
||||
}
|
||||
},
|
||||
"skipPreviouslyDownloadedModelVersions": {
|
||||
"label": "Ignorer les versions de modèles précédemment téléchargées",
|
||||
"help": "Lorsque activé, LoRA Manager ignorera le téléchargement d'une version de modèle si le service d'historique des téléchargements enregistre cette version exacte comme déjà téléchargée. S'applique à tous les flux de téléchargement."
|
||||
},
|
||||
"layoutSettings": {
|
||||
"displayDensity": "Densité d'affichage",
|
||||
"displayDensityOptions": {
|
||||
@@ -827,7 +831,7 @@
|
||||
},
|
||||
"contextMenu": {
|
||||
"moveToOtherTypeFolder": "Déplacer vers le dossier {otherType}",
|
||||
"sendToWorkflow": "[TODO: Translate] Send to Workflow"
|
||||
"sendToWorkflow": "Envoyer vers le workflow"
|
||||
}
|
||||
},
|
||||
"embeddings": {
|
||||
|
||||
@@ -341,6 +341,10 @@
|
||||
"saveFailed": "לא ניתן לשמור את מודלי הבסיס המוחרגים: {message}"
|
||||
}
|
||||
},
|
||||
"skipPreviouslyDownloadedModelVersions": {
|
||||
"label": "דלג על גרסאות מודלים שהורדו בעבר",
|
||||
"help": "כאשר מופעל, LoRA Manager ידלג על הורדת גרסת מודל אם שירות היסטוריית ההורדות רושם את הגרסה המדויקת הזו ככבר שהורדה. חל על כל תהליכי ההורדה."
|
||||
},
|
||||
"layoutSettings": {
|
||||
"displayDensity": "צפיפות תצוגה",
|
||||
"displayDensityOptions": {
|
||||
@@ -827,7 +831,7 @@
|
||||
},
|
||||
"contextMenu": {
|
||||
"moveToOtherTypeFolder": "העבר לתיקיית {otherType}",
|
||||
"sendToWorkflow": "[TODO: Translate] Send to Workflow"
|
||||
"sendToWorkflow": "שלח ל-workflow"
|
||||
}
|
||||
},
|
||||
"embeddings": {
|
||||
|
||||
@@ -341,6 +341,10 @@
|
||||
"saveFailed": "除外するベースモデルを保存できませんでした: {message}"
|
||||
}
|
||||
},
|
||||
"skipPreviouslyDownloadedModelVersions": {
|
||||
"label": "以前にダウンロードしたモデルバージョンをスキップ",
|
||||
"help": "有効にすると、ダウンロード履歴サービスがそのバージョンが既にダウンロード済みと記録している場合、LoRA Managerはそのモデルバージョンのダウンロードをスキップします。すべてのダウンロードフローに適用されます。"
|
||||
},
|
||||
"layoutSettings": {
|
||||
"displayDensity": "表示密度",
|
||||
"displayDensityOptions": {
|
||||
@@ -827,7 +831,7 @@
|
||||
},
|
||||
"contextMenu": {
|
||||
"moveToOtherTypeFolder": "{otherType} フォルダに移動",
|
||||
"sendToWorkflow": "[TODO: Translate] Send to Workflow"
|
||||
"sendToWorkflow": "ワークフローに送信"
|
||||
}
|
||||
},
|
||||
"embeddings": {
|
||||
|
||||
@@ -341,6 +341,10 @@
|
||||
"saveFailed": "제외된 기본 모델을 저장할 수 없습니다: {message}"
|
||||
}
|
||||
},
|
||||
"skipPreviouslyDownloadedModelVersions": {
|
||||
"label": "이전에 다운로드한 모델 버전 건너뛰기",
|
||||
"help": "활성화하면 다운로드 기록 서비스가 해당 버전이 이미 다운로드되었음을 기록한 경우 LoRA Manager는 해당 모델 버전 다운로드를 건너뜁니다. 모든 다운로드 플로우에 적용됩니다."
|
||||
},
|
||||
"layoutSettings": {
|
||||
"displayDensity": "표시 밀도",
|
||||
"displayDensityOptions": {
|
||||
@@ -827,7 +831,7 @@
|
||||
},
|
||||
"contextMenu": {
|
||||
"moveToOtherTypeFolder": "{otherType} 폴더로 이동",
|
||||
"sendToWorkflow": "[TODO: Translate] Send to Workflow"
|
||||
"sendToWorkflow": "워크플로우로 전송"
|
||||
}
|
||||
},
|
||||
"embeddings": {
|
||||
|
||||
@@ -341,6 +341,10 @@
|
||||
"saveFailed": "Не удалось сохранить исключённые базовые модели: {message}"
|
||||
}
|
||||
},
|
||||
"skipPreviouslyDownloadedModelVersions": {
|
||||
"label": "Пропускать ранее загруженные версии моделей",
|
||||
"help": "Если включено, LoRA Manager будет пропускать загрузку версии модели, если сервис истории загрузок записал, что эта конкретная версия уже загружена. Применяется ко всем потокам загрузки."
|
||||
},
|
||||
"layoutSettings": {
|
||||
"displayDensity": "Плотность отображения",
|
||||
"displayDensityOptions": {
|
||||
@@ -827,7 +831,7 @@
|
||||
},
|
||||
"contextMenu": {
|
||||
"moveToOtherTypeFolder": "Переместить в папку {otherType}",
|
||||
"sendToWorkflow": "[TODO: Translate] Send to Workflow"
|
||||
"sendToWorkflow": "Отправить в workflow"
|
||||
}
|
||||
},
|
||||
"embeddings": {
|
||||
|
||||
@@ -341,6 +341,10 @@
|
||||
"saveFailed": "无法保存已排除的基础模型:{message}"
|
||||
}
|
||||
},
|
||||
"skipPreviouslyDownloadedModelVersions": {
|
||||
"label": "跳过已下载的模型版本",
|
||||
"help": "启用后,如果下载历史服务记录显示该版本已下载,LoRA Manager 将跳过下载该模型版本。适用于所有下载流程。"
|
||||
},
|
||||
"layoutSettings": {
|
||||
"displayDensity": "显示密度",
|
||||
"displayDensityOptions": {
|
||||
@@ -827,7 +831,7 @@
|
||||
},
|
||||
"contextMenu": {
|
||||
"moveToOtherTypeFolder": "移动到 {otherType} 文件夹",
|
||||
"sendToWorkflow": "[TODO: Translate] Send to Workflow"
|
||||
"sendToWorkflow": "发送到工作流"
|
||||
}
|
||||
},
|
||||
"embeddings": {
|
||||
|
||||
@@ -341,6 +341,10 @@
|
||||
"saveFailed": "無法儲存已排除的基礎模型:{message}"
|
||||
}
|
||||
},
|
||||
"skipPreviouslyDownloadedModelVersions": {
|
||||
"label": "跳過已下載的模型版本",
|
||||
"help": "啟用後,如果下載歷史服務記錄顯示該版本已下載,LoRA Manager 將跳過下載該模型版本。適用於所有下載流程。"
|
||||
},
|
||||
"layoutSettings": {
|
||||
"displayDensity": "顯示密度",
|
||||
"displayDensityOptions": {
|
||||
@@ -827,7 +831,7 @@
|
||||
},
|
||||
"contextMenu": {
|
||||
"moveToOtherTypeFolder": "移動到 {otherType} 資料夾",
|
||||
"sendToWorkflow": "[TODO: Translate] Send to Workflow"
|
||||
"sendToWorkflow": "傳送到工作流"
|
||||
}
|
||||
},
|
||||
"embeddings": {
|
||||
|
||||
@@ -64,6 +64,19 @@ class DownloadManager:
|
||||
"""Get the checkpoint scanner from registry"""
|
||||
return await ServiceRegistry.get_checkpoint_scanner()
|
||||
|
||||
async def _has_been_downloaded(self, model_type: str, model_version_id: int) -> bool:
|
||||
try:
|
||||
history_service = await ServiceRegistry.get_downloaded_version_history_service()
|
||||
return await history_service.has_been_downloaded(model_type, model_version_id)
|
||||
except Exception as exc:
|
||||
logger.debug(
|
||||
"Failed to read download history for %s version %s: %s",
|
||||
model_type,
|
||||
model_version_id,
|
||||
exc,
|
||||
)
|
||||
return False
|
||||
|
||||
async def download_from_civitai(
|
||||
self,
|
||||
model_id: int = None,
|
||||
@@ -355,6 +368,57 @@ class DownloadManager:
|
||||
"error": f'Model type "{model_type_from_info}" is not supported for download',
|
||||
}
|
||||
|
||||
resolved_version_id = model_version_id
|
||||
raw_version_id = version_info.get("id")
|
||||
if resolved_version_id is None and raw_version_id is not None:
|
||||
try:
|
||||
resolved_version_id = int(raw_version_id)
|
||||
except (TypeError, ValueError):
|
||||
resolved_version_id = None
|
||||
|
||||
if (
|
||||
get_settings_manager().get_skip_previously_downloaded_model_versions()
|
||||
and resolved_version_id is not None
|
||||
and await self._has_been_downloaded(model_type, resolved_version_id)
|
||||
):
|
||||
file_name = ""
|
||||
files = version_info.get("files")
|
||||
if isinstance(files, list):
|
||||
primary_file = next(
|
||||
(
|
||||
file_info
|
||||
for file_info in files
|
||||
if isinstance(file_info, dict) and file_info.get("primary")
|
||||
),
|
||||
None,
|
||||
)
|
||||
selected_file = primary_file
|
||||
if selected_file is None:
|
||||
selected_file = next(
|
||||
(file_info for file_info in files if isinstance(file_info, dict)),
|
||||
None,
|
||||
)
|
||||
if isinstance(selected_file, dict):
|
||||
raw_file_name = selected_file.get("name", "")
|
||||
if isinstance(raw_file_name, str):
|
||||
file_name = raw_file_name.strip()
|
||||
|
||||
message = (
|
||||
f"Skipped download for '{file_name or version_info.get('name') or f'model_version:{resolved_version_id}'}' "
|
||||
f"because version {resolved_version_id} was already downloaded before"
|
||||
)
|
||||
logger.info(message)
|
||||
return {
|
||||
"success": True,
|
||||
"skipped": True,
|
||||
"status": "skipped",
|
||||
"reason": "previously_downloaded_version",
|
||||
"message": message,
|
||||
"model_version_id": resolved_version_id,
|
||||
"file_name": file_name,
|
||||
"download_id": download_id,
|
||||
}
|
||||
|
||||
excluded_base_models = get_settings_manager().get_download_skip_base_models()
|
||||
base_model_value = version_info.get("baseModel", "")
|
||||
if (
|
||||
|
||||
@@ -91,6 +91,7 @@ DEFAULT_SETTINGS: Dict[str, Any] = {
|
||||
"update_flag_strategy": "same_base",
|
||||
"auto_organize_exclusions": [],
|
||||
"metadata_refresh_skip_paths": [],
|
||||
"skip_previously_downloaded_model_versions": False,
|
||||
"download_skip_base_models": [],
|
||||
}
|
||||
|
||||
@@ -314,6 +315,10 @@ class SettingsManager:
|
||||
self.settings["download_skip_base_models"] = []
|
||||
inserted_defaults = True
|
||||
|
||||
if "skip_previously_downloaded_model_versions" not in self.settings:
|
||||
self.settings["skip_previously_downloaded_model_versions"] = False
|
||||
inserted_defaults = True
|
||||
|
||||
had_mature_level = "mature_blur_level" in self.settings
|
||||
raw_mature_level = self.settings.get("mature_blur_level")
|
||||
normalized_mature_level = self.normalize_mature_blur_level(raw_mature_level)
|
||||
@@ -1090,6 +1095,17 @@ class SettingsManager:
|
||||
self._save_settings()
|
||||
return base_models
|
||||
|
||||
def get_skip_previously_downloaded_model_versions(self) -> bool:
|
||||
value = self.settings.get("skip_previously_downloaded_model_versions", False)
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
normalized = False
|
||||
if isinstance(value, str):
|
||||
normalized = value.strip().lower() in {"1", "true", "yes", "on"}
|
||||
self.settings["skip_previously_downloaded_model_versions"] = normalized
|
||||
self._save_settings()
|
||||
return normalized
|
||||
|
||||
def get_extra_folder_paths(self) -> Dict[str, List[str]]:
|
||||
"""Get extra folder paths for the active library.
|
||||
|
||||
|
||||
@@ -146,6 +146,10 @@ export class SettingsManager {
|
||||
backendSettings?.metadata_refresh_skip_paths ?? defaults.metadata_refresh_skip_paths
|
||||
);
|
||||
|
||||
merged.skip_previously_downloaded_model_versions =
|
||||
backendSettings?.skip_previously_downloaded_model_versions
|
||||
?? defaults.skip_previously_downloaded_model_versions;
|
||||
|
||||
merged.download_skip_base_models = this.normalizeDownloadSkipBaseModels(
|
||||
backendSettings?.download_skip_base_models ?? defaults.download_skip_base_models
|
||||
);
|
||||
@@ -836,6 +840,12 @@ export class SettingsManager {
|
||||
hideEarlyAccessUpdatesCheckbox.checked = state.global.settings.hide_early_access_updates || false;
|
||||
}
|
||||
|
||||
const skipPreviouslyDownloadedModelVersionsCheckbox = document.getElementById('skipPreviouslyDownloadedModelVersions');
|
||||
if (skipPreviouslyDownloadedModelVersionsCheckbox) {
|
||||
skipPreviouslyDownloadedModelVersionsCheckbox.checked =
|
||||
state.global.settings.skip_previously_downloaded_model_versions || false;
|
||||
}
|
||||
|
||||
// Set optimize example images setting
|
||||
const optimizeExampleImagesCheckbox = document.getElementById('optimizeExampleImages');
|
||||
if (optimizeExampleImagesCheckbox) {
|
||||
|
||||
@@ -38,6 +38,7 @@ const DEFAULT_SETTINGS_BASE = Object.freeze({
|
||||
hide_early_access_updates: false,
|
||||
auto_organize_exclusions: [],
|
||||
metadata_refresh_skip_paths: [],
|
||||
skip_previously_downloaded_model_versions: false,
|
||||
download_skip_base_models: [],
|
||||
});
|
||||
|
||||
|
||||
@@ -735,6 +735,24 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<div class="setting-row">
|
||||
<div class="setting-info">
|
||||
<label for="skipPreviouslyDownloadedModelVersions">
|
||||
{{ t('settings.skipPreviouslyDownloadedModelVersions.label') }}
|
||||
<i class="fas fa-info-circle info-icon" data-tooltip="{{ t('settings.skipPreviouslyDownloadedModelVersions.help') }}"></i>
|
||||
</label>
|
||||
</div>
|
||||
<div class="setting-control">
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="skipPreviouslyDownloadedModelVersions"
|
||||
onchange="settingsManager.saveToggleSetting('skipPreviouslyDownloadedModelVersions', 'skip_previously_downloaded_model_versions')">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<div class="setting-row">
|
||||
<div class="setting-info">
|
||||
|
||||
@@ -20,6 +20,7 @@ vi.mock('../../../static/js/state/index.js', () => {
|
||||
},
|
||||
createDefaultSettings: () => ({
|
||||
language: 'en',
|
||||
skip_previously_downloaded_model_versions: false,
|
||||
download_skip_base_models: [],
|
||||
}),
|
||||
};
|
||||
@@ -117,6 +118,7 @@ describe('SettingsManager download skip base models UI', () => {
|
||||
document.body.innerHTML = '';
|
||||
vi.clearAllMocks();
|
||||
state.global.settings = {
|
||||
skip_previously_downloaded_model_versions: false,
|
||||
download_skip_base_models: [],
|
||||
};
|
||||
});
|
||||
@@ -150,4 +152,31 @@ describe('SettingsManager download skip base models UI', () => {
|
||||
expect(document.querySelectorAll('#downloadSkipBaseModelsContainer input')).toHaveLength(0);
|
||||
expect(document.getElementById('downloadSkipBaseModelsEmpty').hidden).toBe(false);
|
||||
});
|
||||
|
||||
it('initializes the previously-downloaded-version toggle from settings', () => {
|
||||
document.body.innerHTML = '<input id="skipPreviouslyDownloadedModelVersions" type="checkbox" />';
|
||||
state.global.settings.skip_previously_downloaded_model_versions = true;
|
||||
const manager = createManager();
|
||||
|
||||
manager.loadSettingsToUI();
|
||||
|
||||
expect(document.getElementById('skipPreviouslyDownloadedModelVersions').checked).toBe(true);
|
||||
});
|
||||
|
||||
it('saves the previously-downloaded-version toggle with the expected setting key', async () => {
|
||||
document.body.innerHTML = '<input id="skipPreviouslyDownloadedModelVersions" type="checkbox" checked />';
|
||||
const manager = createManager();
|
||||
manager.saveSetting = vi.fn().mockResolvedValue();
|
||||
manager.applyFrontendSettings = vi.fn();
|
||||
|
||||
await manager.saveToggleSetting(
|
||||
'skipPreviouslyDownloadedModelVersions',
|
||||
'skip_previously_downloaded_model_versions',
|
||||
);
|
||||
|
||||
expect(manager.saveSetting).toHaveBeenCalledWith(
|
||||
'skip_previously_downloaded_model_versions',
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -38,6 +38,7 @@ def isolate_settings(monkeypatch, tmp_path):
|
||||
"embedding": "{base_model}/{first_tag}",
|
||||
},
|
||||
"base_model_path_mappings": {"BaseModel": "MappedModel"},
|
||||
"skip_previously_downloaded_model_versions": False,
|
||||
"download_skip_base_models": [],
|
||||
}
|
||||
)
|
||||
@@ -454,7 +455,7 @@ async def test_download_skips_excluded_base_model(monkeypatch, scanners, metadat
|
||||
|
||||
metadata_provider.get_model_version = AsyncMock(
|
||||
return_value={
|
||||
"id": 42,
|
||||
"id": 99,
|
||||
"model": {"type": "LoRA", "tags": ["fantasy"]},
|
||||
"baseModel": "SDXL 1.0",
|
||||
"creator": {"username": "Author"},
|
||||
@@ -490,3 +491,104 @@ async def test_download_skips_excluded_base_model(monkeypatch, scanners, metadat
|
||||
assert "file.safetensors" in result["message"]
|
||||
execute_download.assert_not_called()
|
||||
assert manager._active_downloads[result["download_id"]]["status"] == "skipped"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_download_skips_previously_downloaded_version(monkeypatch, scanners, metadata_provider):
|
||||
manager = DownloadManager()
|
||||
get_settings_manager().settings["skip_previously_downloaded_model_versions"] = True
|
||||
|
||||
metadata_provider.get_model_version = AsyncMock(
|
||||
return_value={
|
||||
"id": 42,
|
||||
"model": {"type": "LoRA", "tags": ["fantasy"]},
|
||||
"baseModel": "SDXL 1.0",
|
||||
"creator": {"username": "Author"},
|
||||
"files": [
|
||||
{
|
||||
"type": "Model",
|
||||
"primary": True,
|
||||
"downloadUrl": "https://example.invalid/file.safetensors",
|
||||
"name": "file.safetensors",
|
||||
}
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
history_service = AsyncMock()
|
||||
history_service.has_been_downloaded = AsyncMock(return_value=True)
|
||||
monkeypatch.setattr(
|
||||
ServiceRegistry,
|
||||
"get_downloaded_version_history_service",
|
||||
AsyncMock(return_value=history_service),
|
||||
)
|
||||
|
||||
execute_download = AsyncMock()
|
||||
monkeypatch.setattr(
|
||||
DownloadManager, "_execute_download", execute_download, raising=False
|
||||
)
|
||||
|
||||
result = await manager.download_from_civitai(
|
||||
model_version_id=99,
|
||||
use_default_paths=True,
|
||||
progress_callback=None,
|
||||
source=None,
|
||||
)
|
||||
|
||||
assert result["success"] is True
|
||||
assert result["skipped"] is True
|
||||
assert result["status"] == "skipped"
|
||||
assert result["reason"] == "previously_downloaded_version"
|
||||
assert result["model_version_id"] == 99
|
||||
assert result["file_name"] == "file.safetensors"
|
||||
history_service.has_been_downloaded.assert_awaited_once_with("lora", 99)
|
||||
execute_download.assert_not_called()
|
||||
assert manager._active_downloads[result["download_id"]]["status"] == "skipped"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_download_proceeds_when_history_skip_disabled(monkeypatch, scanners, metadata_provider):
|
||||
manager = DownloadManager()
|
||||
get_settings_manager().settings["skip_previously_downloaded_model_versions"] = False
|
||||
|
||||
metadata_provider.get_model_version = AsyncMock(
|
||||
return_value={
|
||||
"id": 42,
|
||||
"model": {"type": "LoRA", "tags": ["fantasy"]},
|
||||
"baseModel": "SDXL 1.0",
|
||||
"creator": {"username": "Author"},
|
||||
"files": [
|
||||
{
|
||||
"type": "Model",
|
||||
"primary": True,
|
||||
"downloadUrl": "https://example.invalid/file.safetensors",
|
||||
"name": "file.safetensors",
|
||||
}
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
history_service = AsyncMock()
|
||||
history_service.has_been_downloaded = AsyncMock(return_value=True)
|
||||
monkeypatch.setattr(
|
||||
ServiceRegistry,
|
||||
"get_downloaded_version_history_service",
|
||||
AsyncMock(return_value=history_service),
|
||||
)
|
||||
|
||||
execute_download = AsyncMock(return_value={"success": True, "download_id": "done"})
|
||||
monkeypatch.setattr(
|
||||
DownloadManager, "_execute_download", execute_download, raising=False
|
||||
)
|
||||
|
||||
result = await manager.download_from_civitai(
|
||||
model_version_id=99,
|
||||
use_default_paths=True,
|
||||
progress_callback=None,
|
||||
source=None,
|
||||
)
|
||||
|
||||
assert result["success"] is True
|
||||
assert result.get("skipped") is not True
|
||||
history_service.has_been_downloaded.assert_not_called()
|
||||
execute_download.assert_awaited_once()
|
||||
|
||||
@@ -829,3 +829,14 @@ def test_setting_download_skip_base_models_normalizes_string_input(manager):
|
||||
manager.set("download_skip_base_models", "SDXL 1.0, Pony; Invalid\nSDXL 1.0")
|
||||
|
||||
assert manager.get("download_skip_base_models") == ["SDXL 1.0", "Pony"]
|
||||
|
||||
|
||||
def test_skip_previously_downloaded_model_versions_defaults_false(manager):
|
||||
assert manager.get_skip_previously_downloaded_model_versions() is False
|
||||
|
||||
|
||||
def test_skip_previously_downloaded_model_versions_coerces_string_input(manager):
|
||||
manager.settings["skip_previously_downloaded_model_versions"] = "true"
|
||||
|
||||
assert manager.get_skip_previously_downloaded_model_versions() is True
|
||||
assert manager.settings["skip_previously_downloaded_model_versions"] is True
|
||||
|
||||
Reference in New Issue
Block a user