refactor: remove dead code and unused frontend handlers across backend and web

This commit is contained in:
Dariusz L
2026-07-18 13:30:34 +02:00
parent b302566542
commit c39eea4f51
9 changed files with 4 additions and 289 deletions
-26
View File
@@ -242,32 +242,6 @@ def _is_civitai_api_download_url(url: str) -> bool:
)
def _resolve_civitai_download_url_for_aria2(
url: str,
headers: Optional[Dict[str, str]] = None,
) -> str:
"""Resolve CivitAI's API download redirect before handing the URL to aria2."""
validated_url = validate_public_http_url(url)
if not _is_civitai_api_download_url(validated_url):
return validated_url
try:
response, resolved_url, _ = request_public_url(
"GET",
validated_url,
headers=build_download_headers(validated_url, headers),
timeout=20,
stream=True,
max_redirects=1,
)
response.close()
log.debug("Resolved CivitAI download redirect for aria2")
return resolved_url
except Exception as exc:
log.warning(f"Could not pre-resolve CivitAI download URL for aria2: {exc}")
return validated_url
def _resolve_download_url_for_aria2(
url: str,
headers: Optional[Dict[str, str]] = None,
-6
View File
@@ -1969,12 +1969,6 @@ def _is_hash_verified_exact_match(result: Optional[Dict[str, Any]], confidence:
return bool(result.get("sha256") or result.get("hash"))
def _build_search_queries(filename: str) -> List[str]:
return build_filename_search_queries(filename)
def search_civarchive(
query: str,
model_type: Optional[str] = None,
-18
View File
@@ -1252,24 +1252,6 @@ def _enrich_model_info_with_details(
return result
def search_civitai_by_hash(
hash_value: str, api_key: Optional[str] = None
) -> Optional[Dict[str, Any]]:
"""Look up a model by file hash on CivitAI."""
result = get_model_info_by_hash(hash_value, api_key=api_key, use_cache=False)
if not result:
return None
return {
"source": result.get("source"),
"model_id": result.get("model_id"),
"version_id": result.get("version_id"),
"name": result.get("model_name") or result.get("name", ""),
"url": result.get("url"),
"download_url": result.get("download_url"),
"filename": result.get("filename", ""),
"size": result.get("size"),
}
def resolve_urn(
model_id: int, version_id: int, api_key: Optional[str] = None
-31
View File
@@ -8,7 +8,6 @@ if parent_dir not in sys.path:
sys.path.insert(0, parent_dir)
from core.matcher import MODEL_TITLE_MATCH_THRESHOLD
from core.sources.civitai import search_civitai_by_hash
from core.sources.lora_manager_archive import _normalize_model_type
from core.type_utils import (
normalize_lora_manager_type,
@@ -65,36 +64,6 @@ class TestRefactoringUnification(unittest.TestCase):
self.assertEqual(res["filename"], "test.safetensors")
self.assertEqual(res["extra_field"], "hello_world")
@patch("core.sources.civitai.get_model_info_by_hash")
def test_search_civitai_by_hash(self, mock_get_info):
mock_get_info.return_value = {
"source": "civitai",
"model_id": 500,
"version_id": 600,
"model_name": "My Civitai Model",
"url": "http://civitai/model",
"download_url": "http://civitai/download",
"filename": "my_model.safetensors",
"size": 9999,
}
res = search_civitai_by_hash("fake_hash", "fake_key")
mock_get_info.assert_called_once_with("fake_hash", api_key="fake_key", use_cache=False)
self.assertIsNotNone(res)
self.assertEqual(res["source"], "civitai")
self.assertEqual(res["model_id"], 500)
self.assertEqual(res["version_id"], 600)
self.assertEqual(res["name"], "My Civitai Model")
self.assertEqual(res["url"], "http://civitai/model")
self.assertEqual(res["download_url"], "http://civitai/download")
self.assertEqual(res["filename"], "my_model.safetensors")
self.assertEqual(res["size"], 9999)
@patch("core.sources.civitai.get_model_info_by_hash")
def test_search_civitai_by_hash_not_found(self, mock_get_info):
mock_get_info.return_value = None
res = search_civitai_by_hash("fake_hash")
self.assertIsNone(res)
@patch("requests.get")
def test_request_page_text_success(self, mock_get):
from core.sources.civarchive import _request_page_text
+3 -15
View File
@@ -14,7 +14,7 @@ from core.downloader import (
get_metadata_sidecar_path,
download_model,
get_progress,
_resolve_civitai_download_url_for_aria2,
_resolve_download_url_for_aria2,
start_aria2_daemon,
_delete_partial_download_files,
download_progress,
@@ -307,10 +307,8 @@ class ModelResolverRobustnessTests(unittest.TestCase):
def test_civitai_redirection_link_resolution_for_aria2(self):
"""
Covers Integration Requirement: Redirect resolution for Aria2.
Verifies _resolve_civitai_download_url_for_aria2 pre-resolves redirect URLs,
and skips non-CivitAI URL requests completely.
Verifies _resolve_download_url_for_aria2 pre-resolves redirect URLs.
"""
# Scenario 1: CivitAI URL redirect
api_url = "https://civitai.com/api/download/models/123"
redirect_url = "https://civitai-delivery.net/models/123/model.safetensors?token=abc"
@@ -328,20 +326,10 @@ class ModelResolverRobustnessTests(unittest.TestCase):
"core.network_utils.validate_public_http_url",
side_effect=lambda value: value,
):
resolved = _resolve_civitai_download_url_for_aria2(api_url)
resolved, _ = _resolve_download_url_for_aria2(api_url)
self.assertEqual(resolved, redirect_url)
self.assertEqual(mock_get.call_count, 2)
# Scenario 2: Non-CivitAI URL (e.g. HuggingFace) should bypass redirects immediately
hf_url = "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/model.safetensors"
with patch("requests.get") as mock_get_hf, patch(
"core.downloader.validate_public_http_url",
side_effect=lambda value: value,
):
resolved_hf = _resolve_civitai_download_url_for_aria2(hf_url)
self.assertEqual(resolved_hf, hf_url)
mock_get_hf.assert_not_called()
def test_job_progress_tracker_clamping_and_thread_safety(self):
"""
Covers Requirement: Thread-safe progress tracking and validation.
-19
View File
@@ -29,7 +29,6 @@ from core.sources.civarchive import (
_normalize_archive_version,
parse_civarchive_url,
_prepare_size_probe_url,
_build_search_queries,
)
# ---------------------------------------------------------------------------
@@ -483,24 +482,6 @@ class PrepareSizeProbeUrlTests(unittest.TestCase):
self.assertIsNone(_prepare_size_probe_url(None))
# ===========================================================================
# civarchive - _build_search_queries
# ===========================================================================
class BuildSearchQueriesTests(unittest.TestCase):
def test_returns_list_of_strings(self):
result = _build_search_queries("my_model_v2.safetensors")
self.assertIsInstance(result, list)
self.assertTrue(all(isinstance(q, str) for q in result))
def test_non_empty_for_valid_filename(self):
result = _build_search_queries("cool-lora-style_v1.safetensors")
self.assertGreater(len(result), 0)
def test_empty_string_returns_list(self):
result = _build_search_queries("")
self.assertIsInstance(result, list)
# ===========================================================================
# civitai - parse_civitai_url
+1
View File
@@ -40,5 +40,6 @@ app.registerExtension({
},
afterConfigureGraph() {
modelResolver.configureWorkflowDependencyMarkerNodes();
modelResolver.checkAndOpenForMissingModels();
},
});
-18
View File
@@ -1540,11 +1540,6 @@ export const queueMethods = {
}
},
// Collapse/expand queue panel
toggleQueueCollapsed() {
this.setQueueCollapsed(!this.queueCollapsed);
},
setQueueCollapsed(collapsed, { persist = true, updatePanel = true } = {}) {
const nextCollapsed = !!collapsed;
const wasCollapsed = !!this.queueCollapsed;
@@ -2907,19 +2902,6 @@ export const queueMethods = {
}
},
/**
* Handle click on Download All / Cancel All button
*/
handleDownloadAllClick() {
if (this.getActiveQueuePanelDownloadIds().length > 0) {
// Cancel all active downloads
this.cancelAllDownloads();
} else {
// Start downloading all missing
this.downloadAllMissing();
}
},
/**
* Cancel all active downloads
*/
-156
View File
@@ -1059,162 +1059,6 @@ export class ModelResolver {
// Run auto-resolve for 100% matches - returns the updated workflow
const updatedWorkflow = await this.dialog.autoResolve100Percent();
// Always open Model Resolver to show remaining unresolved models
// Pass the updated workflow if available to avoid race condition
this.dialog.show(updatedWorkflow || null);
}
/**
* Mark resolved model items in the popup as linked (green) and hide download buttons
*/
removeResolvedFromPopup(dialog, resolvedFilenames) {
log.debug('Model Resolver: Looking for resolved filenames:', resolvedFilenames);
// Strategy: For each filename, find text nodes containing it,
// then find the nearest Download button and mark that row
for (const filename of resolvedFilenames) {
// Get all text in the dialog and find elements containing our filename
const walker = document.createTreeWalker(
dialog,
NodeFilter.SHOW_TEXT,
null,
false
);
let node;
while ((node = walker.nextNode())) {
if (node.textContent?.toLowerCase().includes(filename)) {
// Found text containing filename - now find parent with Download button
let parent = node.parentElement;
let attempts = 0;
while (parent && parent !== dialog && attempts < 10) {
// Look for Download button at this level
const downloadBtn = Array.from(parent.querySelectorAll('button'))
.find(btn => btn.textContent?.includes('Download') &&
!btn.id?.includes('model-resolver'));
if (downloadBtn) {
log.debug('Model Resolver: Found entry for', filename);
this.markEntryAsResolved(parent, downloadBtn);
break;
}
parent = parent.parentElement;
attempts++;
}
// Only process first match for this filename
break;
}
}
}
}
/**
* Mark a model entry as resolved with visual feedback
*/
markEntryAsResolved(container, downloadBtn) {
// Already marked?
if (container.dataset.resolved === 'true') return;
container.dataset.resolved = 'true';
log.debug('Model Resolver: Marking entry as resolved', container);
// Add green background/styling to the container
container.classList.add('mr-resolved-entry');
// Hide the Download button and replace with badge
if (downloadBtn) {
// Create badge
const badge = document.createElement('span');
badge.className = 'mr-resolved-badge';
badge.textContent = '✓ Linked';
// Replace download button with badge
downloadBtn.style.display = 'none';
downloadBtn.parentElement?.insertBefore(badge, downloadBtn);
}
// Find and hide Copy URL button
const allBtns = container.querySelectorAll('button');
for (const btn of allBtns) {
if (btn.textContent?.includes('Copy URL')) {
btn.style.display = 'none';
}
}
}
/**
* Count remaining model items in the popup
*/
countRemainingItems(dialog) {
// Count elements that look like model entries (have Download buttons)
const downloadButtons = dialog.querySelectorAll('button');
let count = 0;
for (const btn of downloadButtons) {
if (btn.textContent?.includes('Download') && !btn.id?.includes('model-resolver')) {
count++;
}
}
return count;
}
/**
* Update nodes directly in the graph without triggering a full workflow reload
* This prevents the Missing Models popup from closing
*/
updateNodesDirectly(resolutions) {
if (!app?.graph) {
console.warn('Model Resolver: Cannot update nodes - graph not available');
return;
}
for (const resolution of resolutions) {
const nodeId = resolution.node_id;
const widgetIndex = resolution.widget_index;
const resolvedPath = resolution.resolved_path;
// Find the node in the graph
const node = app.graph.getNodeById(nodeId);
if (!node) {
console.warn(`Model Resolver: Node ${nodeId} not found in graph`);
continue;
}
// Update the widget value
if (node.widgets && node.widgets[widgetIndex]) {
const widget = node.widgets[widgetIndex];
widget.value = resolvedPath;
// Trigger widget callback if it exists
if (widget.callback) {
widget.callback(resolvedPath, app.graph, node, null, null);
}
log.debug(`Model Resolver: Updated node ${nodeId} widget ${widgetIndex} to ${resolvedPath}`);
} else if (node.widgets_values) {
// Fallback: update widgets_values array directly
node.widgets_values[widgetIndex] = resolvedPath;
log.debug(`Model Resolver: Updated node ${nodeId} widgets_values[${widgetIndex}] to ${resolvedPath}`);
}
// Mark node as dirty to trigger redraw
if (node.setDirtyCanvas) {
node.setDirtyCanvas(true, true);
}
}
// Trigger canvas redraw
if (app.graph.setDirtyCanvas) {
app.graph.setDirtyCanvas(true, true);
}
}
/**
* Check if auto-open is enabled in user settings
*/
isAutoOpenEnabled() {
return localStorage.getItem('ModelResolver.autoOpenOnMissing') !== 'false';
}