diff --git a/.gitignore b/.gitignore index 42be4fc..655d061 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ ENV/ # IDE .vscode/ .idea/ +AGENTS.md *.swp *.swo *~ diff --git a/__init__.py b/__init__.py index be6e50c..89ddde1 100644 --- a/__init__.py +++ b/__init__.py @@ -25,9 +25,8 @@ if not __package__ or __package__ == "": sys.modules[package_name] = current_module if not hasattr(current_module, "__path__"): current_module.__path__ = [this_dir] -from .core.log_system.log_funcs import create_module_logger +from .core.log_system import LogLevel, create_module_logger, logger as backend_log_controller from .core.log_system.config import LOG_LEVEL as BACKEND_DEFAULT_LOG_LEVEL -from .core.log_system.logger import LogLevel, logger as backend_log_controller # Web directory for JavaScript interface WEB_DIRECTORY = "./web" diff --git a/core/downloader.py b/core/downloader.py index 94ace57..9059037 100644 --- a/core/downloader.py +++ b/core/downloader.py @@ -19,7 +19,7 @@ from pathlib import Path from collections import deque from urllib.parse import parse_qsl, urlencode, urljoin, urlparse, urlunparse -from .log_system.log_funcs import create_module_logger +from .log_system import create_module_logger log = create_module_logger(__name__) from .resolver import normalize_sha256 @@ -196,7 +196,7 @@ def _resolve_civitai_download_url_for_aria2( log.debug("Resolved CivitAI download redirect for aria2") return resolved_url except Exception as exc: - log.warn(f"Could not pre-resolve CivitAI download URL for aria2: {exc}") + log.warning(f"Could not pre-resolve CivitAI download URL for aria2: {exc}") return url finally: if response is not None: @@ -628,7 +628,7 @@ def write_lora_manager_metadata( log.info(f"Metadata saved: {metadata_path}") return metadata_path except Exception as e: - log.warn(f"Could not save metadata sidecar for {dest_path}: {e}") + log.warning(f"Could not save metadata sidecar for {dest_path}: {e}") return None @@ -1149,7 +1149,7 @@ def _delete_partial_download_files(dest_path: str) -> None: if path and os.path.exists(path): os.remove(path) except Exception as exc: - log.warn(f"Could not delete incomplete download file {path}: {exc}") + log.warning(f"Could not delete incomplete download file {path}: {exc}") def download_file_with_aria2( @@ -1561,7 +1561,7 @@ def download_file( else: log.info(f"Cancelled: {filename} - no file to delete") except Exception as e: - log.warn(f"Could not delete incomplete file {dest_path}: {e}") + log.warning(f"Could not delete incomplete file {dest_path}: {e}") # Try harder on Windows - sometimes the file handle takes a moment to release try: time.sleep(0.5) # time is already imported at module level @@ -1722,7 +1722,7 @@ def download_model( error_msg = ( f"File already exists and its SHA256 could not be verified: {dest_path}" ) - log.warn(f"{error_msg} ({e})") + log.warning(f"{error_msg} ({e})") return { "success": False, "download_id": download_id, @@ -1778,7 +1778,7 @@ def download_model( "File already exists, but its SHA256 does not match the selected " f"source: {dest_path}" ) - log.warn( + log.warning( f"{error_msg} (existing={existing_sha256}, expected={expected_sha256})" ) return { @@ -1823,7 +1823,7 @@ def _force_remove_aria2_transfer(download_id: str, gid: str) -> None: try: _aria2_rpc("aria2.forceRemove", [gid]) except Exception as exc: - log.warn(f"Could not cancel aria2 download {download_id}: {exc}") + log.warning(f"Could not cancel aria2 download {download_id}: {exc}") def _get_aria2_action_lock(download_id: str) -> threading.Lock: @@ -1884,7 +1884,7 @@ def _run_aria2_desired_state_worker(download_id: str) -> None: if _aria2_action_error_is_ok(desired_status, str(exc)): _set_download_progress_status(download_id, desired_status, speed=0 if desired_status == "paused" else download_progress.get(download_id, {}).get("speed", 0)) else: - log.warn(f"aria2 {desired_status} action failed for {download_id}: {exc}") + log.warning(f"aria2 {desired_status} action failed for {download_id}: {exc}") with aria2_lock: latest = aria2_desired_states.get(download_id) diff --git a/core/matcher.py b/core/matcher.py index f5d4b47..43c9327 100644 --- a/core/matcher.py +++ b/core/matcher.py @@ -10,7 +10,7 @@ import heapq from typing import List, Dict, Tuple, Optional from difflib import SequenceMatcher -from .log_system.log_funcs import create_module_logger +from .log_system import create_module_logger log = create_module_logger(__name__) try: diff --git a/core/path_utils.py b/core/path_utils.py index 44abf20..660aa7d 100644 --- a/core/path_utils.py +++ b/core/path_utils.py @@ -18,7 +18,7 @@ def _get_log(): """Return a lazily-created module logger (avoids circular imports).""" global _log if _log is None: - from .log_system.log_funcs import create_module_logger + from .log_system import create_module_logger _log = create_module_logger(__name__) return _log diff --git a/core/progress.py b/core/progress.py index 2cc62b4..f14b522 100644 --- a/core/progress.py +++ b/core/progress.py @@ -5,7 +5,7 @@ Unified utility for reporting progress of asynchronous search and download opera """ from typing import Dict, Any, Optional, Callable -from .log_system.log_funcs import create_module_logger +from .log_system import create_module_logger log = create_module_logger(__name__) diff --git a/core/resolver.py b/core/resolver.py index 4b2ad4a..00bc723 100644 --- a/core/resolver.py +++ b/core/resolver.py @@ -10,7 +10,7 @@ import json from typing import Dict, Any, List, Optional, Tuple, Callable from urllib.parse import unquote -from .log_system.log_funcs import create_module_logger +from .log_system import create_module_logger log = create_module_logger(__name__) from .scanner import get_model_files diff --git a/core/scanner.py b/core/scanner.py index d357362..062692d 100644 --- a/core/scanner.py +++ b/core/scanner.py @@ -8,7 +8,7 @@ import os import time from typing import List, Dict, Tuple, Optional -from .log_system.log_funcs import create_module_logger +from .log_system import create_module_logger log = create_module_logger(__name__) @@ -20,7 +20,7 @@ try: import folder_paths except ImportError: folder_paths = None - log.warn("Model Resolver: folder_paths not available yet - will retry later") + log.warning("Model Resolver: folder_paths not available yet - will retry later") _MODEL_FILES_CACHE: Optional[List[Dict[str, str]]] = None _MODEL_FILES_CACHE_AT: float = 0.0 @@ -192,7 +192,7 @@ def scan_directory( } ) except (OSError, PermissionError) as e: - log.warn(f"Error scanning directory {directory}: {e}") + log.warning(f"Error scanning directory {directory}: {e}") return models @@ -242,7 +242,7 @@ def scan_all_directories() -> List[Dict[str, str]]: elif raw_exts: extensions = {str(raw_exts).lower()} except Exception as e: - log.warn(f"Error interpreting folder_paths entry for {category}: {e}") + log.warning(f"Error interpreting folder_paths entry for {category}: {e}") continue for directory_path in paths: @@ -268,7 +268,7 @@ def scan_all_directories() -> List[Dict[str, str]]: all_models.append(model) #log.debug(f"Found {len(models)} models in {category}/{directory_path}") except Exception as e: - log.warn(f"Error scanning {category} directory {directory_path}: {e}") + log.warning(f"Error scanning {category} directory {directory_path}: {e}") return all_models diff --git a/core/sources/__init__.py b/core/sources/__init__.py index 345cb90..e542672 100644 --- a/core/sources/__init__.py +++ b/core/sources/__init__.py @@ -4,7 +4,7 @@ Model Sources Module Provides search functionality for finding models from various sources. """ -from ..log_system.log_funcs import create_module_logger # noqa: F401 +from ..log_system import create_module_logger # noqa: F401 from .popular import search_popular_models, get_popular_model_url from .model_list import search_model_list, search_model_list_multiple diff --git a/core/sources/civarchive.py b/core/sources/civarchive.py index e8cc78b..82a4cf9 100644 --- a/core/sources/civarchive.py +++ b/core/sources/civarchive.py @@ -37,7 +37,7 @@ from ..type_utils import ( normalize_model_image, ) from ..progress import report_progress, get_progress_reporter -from ..log_system.log_funcs import create_module_logger +from ..log_system import create_module_logger log = create_module_logger(__name__) @@ -137,7 +137,7 @@ def _extract_next_data(html_text: str) -> Dict[str, Any]: try: return json.loads(html.unescape(match.group(1))) except Exception as e: - log.warn(f"CivArchive search JSON parse failed: {e}") + log.warning(f"CivArchive search JSON parse failed: {e}") return {} @@ -158,7 +158,7 @@ def _request_json( timeout=timeout, ) except Exception as e: - log.warn(f"CivArchive API request failed: path={path}, error={e}") + log.warning(f"CivArchive API request failed: path={path}, error={e}") return None if response.status_code != 429 or attempt == 1: @@ -181,7 +181,7 @@ def _request_json( try: return response.json() except Exception as e: - log.warn(f"CivArchive API JSON parse failed: path={path}, error={e}") + log.warning(f"CivArchive API JSON parse failed: path={path}, error={e}") return None @@ -211,7 +211,7 @@ def _request_page_text( timeout=timeout, ) except Exception as e: - log.warn(f"CivArchive page request failed: url={url}, error={e}") + log.warning(f"CivArchive page request failed: url={url}, error={e}") return None if response.status_code != 200: @@ -472,11 +472,11 @@ def _search_page( timeout=timeout, ) except Exception as e: - log.warn(f"CivArchive search request failed: query={query}, error={e}") + log.warning(f"CivArchive search request failed: query={query}, error={e}") raise CivArchiveSearchError(str(e)) from e if response.status_code != 200: - log.warn( + log.warning( f"CivArchive search returned {response.status_code}: query={query}" ) raise CivArchiveSearchError(f"HTTP {response.status_code}") diff --git a/core/sources/civitai.py b/core/sources/civitai.py index 84ee028..10148f1 100644 --- a/core/sources/civitai.py +++ b/core/sources/civitai.py @@ -33,7 +33,7 @@ from ..type_utils import ( ) from ..progress import report_progress, get_progress_reporter from ..path_utils import calculate_file_sha256, get_filename_from_path -from ..log_system.log_funcs import create_module_logger +from ..log_system import create_module_logger log = create_module_logger(__name__) @@ -408,7 +408,7 @@ def _search_civitai_trpc_candidates( try: response = requests.get(url, headers=headers, timeout=timeout) except Exception as e: - log.warn(f"CivitAI tRPC request failed for filename={filename}: {e}") + log.warning(f"CivitAI tRPC request failed for filename={filename}: {e}") return [] text_preview = response.text[:800].replace("\n", " ").replace("\r", " ") @@ -422,7 +422,7 @@ def _search_civitai_trpc_candidates( try: payload = response.json() except Exception as e: - log.warn(f"CivitAI tRPC JSON parse failed for filename={filename}: {e}") + log.warning(f"CivitAI tRPC JSON parse failed for filename={filename}: {e}") return [] candidates = _extract_trpc_model_candidates(payload, limit=limit) @@ -441,7 +441,7 @@ def _search_civitai_red_candidates( response = requests.get(search_url, timeout=timeout) if response.status_code != 200: - log.warn( + log.warning( f"CivitAI.red search returned {response.status_code} for filename={filename}" ) return [] @@ -536,7 +536,7 @@ def _find_civitai_file_in_model( f"{CIVITAI_API_URL}/models/{model_id}", headers=headers, timeout=15 ) if response.status_code != 200: - log.warn(f"CivitAI model lookup returned {response.status_code} for model_id={model_id}") + log.warning(f"CivitAI model lookup returned {response.status_code} for model_id={model_id}") return None data = response.json() @@ -986,7 +986,7 @@ def get_civitai_model_details( timeout=20, ) if response.status_code != 200: - log.warn(f"CivitAI model details returned {response.status_code}: model_id={model_id}") + log.warning(f"CivitAI model details returned {response.status_code}: model_id={model_id}") return None data = response.json() @@ -1162,7 +1162,7 @@ def resolve_urn( response = requests.get(url, headers=headers, params=params, timeout=15) if response.status_code != 200: - log.warn(f"CivitAI URN resolve failed: {response.status_code}") + log.warning(f"CivitAI URN resolve failed: {response.status_code}") _urn_cache[cache_key] = None return None @@ -1170,7 +1170,7 @@ def resolve_urn( versions = data.get("modelVersions", []) if not versions: - log.warn(f"No versions found for model {model_id}/version {version_id}") + log.warning(f"No versions found for model {model_id}/version {version_id}") _urn_cache[cache_key] = None return None @@ -1182,7 +1182,7 @@ def resolve_urn( break if not target_version: - log.warn(f"Version {version_id} not found in model {model_id}") + log.warning(f"Version {version_id} not found in model {model_id}") _urn_cache[cache_key] = None return None @@ -1199,7 +1199,7 @@ def resolve_urn( primary_file = files[0] # Fallback to first if not primary_file: - log.warn(f"No files found for version {version_id}") + log.warning(f"No files found for version {version_id}") _urn_cache[cache_key] = None return None @@ -1322,7 +1322,7 @@ def get_model_info_by_hash( _hash_cache[cache_key] = None return None else: - log.warn( + log.warning( f"CivitAI hash lookup returned {response.status_code} for {file_hash}" ) return None @@ -1395,7 +1395,7 @@ def get_model_info_by_hash( _hash_cache[cache_key] = None return None else: - log.warn( + log.warning( f"CivitAI hash lookup returned {response.status_code} for {file_hash}" ) return None diff --git a/core/sources/huggingface.py b/core/sources/huggingface.py index 5806dad..c9fb901 100644 --- a/core/sources/huggingface.py +++ b/core/sources/huggingface.py @@ -14,7 +14,7 @@ from typing import Dict, Any, Optional, List, Callable from urllib.parse import urlparse, quote from ..progress import report_progress, get_progress_reporter -from ..log_system.log_funcs import create_module_logger +from ..log_system import create_module_logger log = create_module_logger(__name__) from ..path_utils import write_json_atomic, METADATA_DIR @@ -255,7 +255,7 @@ def _get_author_index( return fresh_index if persistent_index: - log.warn( + log.warning( f"Using stale HuggingFace author index for author={author}; refresh failed" ) _author_index_cache[cache_key] = persistent_index @@ -642,7 +642,7 @@ def _search_brave_for_huggingface_candidates( BRAVE_SEARCH_API_URL, headers=headers, params=params, timeout=15 ) if response.status_code != 200: - log.warn( + log.warning( f"Brave search returned {response.status_code} for query={query}" ) return [] @@ -760,7 +760,7 @@ def search_huggingface_for_file( search_url = f"{HF_API_URL}/models?search={quote(search_query)}&limit=20" response = requests.get(search_url, headers=headers, timeout=10) if response.status_code != 200: - log.warn( + log.warning( f"HuggingFace API status={response.status_code} query={search_query}" ) continue diff --git a/core/sources/lora_manager_archive.py b/core/sources/lora_manager_archive.py index 16e3b59..5182d10 100644 --- a/core/sources/lora_manager_archive.py +++ b/core/sources/lora_manager_archive.py @@ -20,7 +20,7 @@ from ..matcher import ( ) from ..type_utils import select_primary_model_file from ..progress import report_progress, get_progress_reporter -from ..log_system.log_funcs import create_module_logger +from ..log_system import create_module_logger log = create_module_logger(__name__) @@ -108,7 +108,7 @@ def _connect_readonly() -> Optional[sqlite3.Connection]: conn.row_factory = sqlite3.Row return conn except Exception as e: - log.warn(f"Failed to open LoRA Manager archive DB: {e}") + log.warning(f"Failed to open LoRA Manager archive DB: {e}") return None diff --git a/core/sources/model_list.py b/core/sources/model_list.py index 16dbbd4..c92b4ef 100644 --- a/core/sources/model_list.py +++ b/core/sources/model_list.py @@ -15,7 +15,7 @@ from urllib.request import Request, urlopen from ..matcher import normalize_filename, calculate_similarity -from ..log_system.log_funcs import create_module_logger +from ..log_system import create_module_logger log = create_module_logger(__name__) @@ -67,7 +67,7 @@ def _get_local_model_list_sha() -> str: header = f"blob {len(content)}\0".encode("utf-8") return hashlib.sha1(header + content).hexdigest() except Exception as e: - log.warn(f"Error calculating model-list.json SHA: {e}") + log.warning(f"Error calculating model-list.json SHA: {e}") return "" diff --git a/core/sources/popular.py b/core/sources/popular.py index cccb25d..69c787a 100644 --- a/core/sources/popular.py +++ b/core/sources/popular.py @@ -12,7 +12,7 @@ import tempfile from datetime import datetime, timezone from typing import Dict, Any, Optional, List -from ..log_system.log_funcs import create_module_logger +from ..log_system import create_module_logger log = create_module_logger(__name__) @@ -285,7 +285,7 @@ def get_base_models_status(check_remote: bool = False) -> Dict[str, Any]: "update_available": new_models_found }) except Exception as e: - log.warn(f"Error checking remote base models: {e}") + log.warning(f"Error checking remote base models: {e}") return status diff --git a/core/workflow_analyzer.py b/core/workflow_analyzer.py index fd9a4c6..c6c4000 100644 --- a/core/workflow_analyzer.py +++ b/core/workflow_analyzer.py @@ -9,7 +9,7 @@ import re import threading from typing import List, Dict, Any, Optional, Set -from .log_system.log_funcs import create_module_logger +from .log_system import create_module_logger log = create_module_logger(__name__) @@ -18,7 +18,7 @@ try: import folder_paths except ImportError: folder_paths = None - log.warn("Model Resolver: folder_paths not available yet - will retry later") + log.warning("Model Resolver: folder_paths not available yet - will retry later") from .type_utils import URN_TYPE_MAP, MODEL_EXTENSIONS @@ -2012,7 +2012,7 @@ def analyze_workflow_models( ) all_model_refs.extend(model_refs) except Exception as e: - log.warn(f"Error analyzing node {node.get('id', 'unknown')}: {e}") + log.warning(f"Error analyzing node {node.get('id', 'unknown')}: {e}") continue # Recursively analyze subgraphs (definitions already loaded above) @@ -2045,7 +2045,7 @@ def analyze_workflow_models( _apply_promoted_widget_locator(ref, promoted_widget_contexts) all_model_refs.extend(model_refs) except Exception as e: - log.warn( + log.warning( f"Error analyzing subgraph node {node.get('id', 'unknown')}: {e}" ) continue diff --git a/core/workflow_updater.py b/core/workflow_updater.py index bae0089..bb11d4d 100644 --- a/core/workflow_updater.py +++ b/core/workflow_updater.py @@ -7,7 +7,7 @@ Updates workflow JSON by replacing model paths in nodes. import os from typing import Dict, Any, List, Optional -from .log_system.log_funcs import create_module_logger +from .log_system import create_module_logger log = create_module_logger(__name__) @@ -201,13 +201,13 @@ def update_model_path( if not node: location = f"subgraph {subgraph_id}" if subgraph_id else "top-level" - log.warn(f"Node {node_id} not found in {location}") + log.warning(f"Node {node_id} not found in {location}") return False widgets_values = node.get("widgets_values", []) if widget_index >= len(widgets_values): - log.warn(f"Widget index {widget_index} out of range for node {node_id}") + log.warning(f"Widget index {widget_index} out of range for node {node_id}") return False # Get category from resolved_model if not provided @@ -289,12 +289,12 @@ def update_model_path( return True else: # Log the actual lora list for debugging - log.warn( + log.warning( f"Lora '{original_lora_name}' not found in lora list. Available: {[li.get('name') for li in lora_list if isinstance(li, dict)]}" ) return False else: - log.warn( + log.warning( f"LoraManager widget_index == 2 but lora_list is not a list: {type(lora_list)}" ) return False @@ -357,7 +357,7 @@ def update_workflow_nodes( resolved_path = mapping.get("resolved_path") if not all([node_id is not None, widget_index is not None, resolved_path]): - log.warn(f"Invalid mapping: {mapping}") + log.warning(f"Invalid mapping: {mapping}") continue # Try to get base_directory from resolved_model if provided