Unify shared path normalization
This commit is contained in:
@@ -12,6 +12,7 @@ from ..path_utils import (
|
||||
MODEL_RESOLVER_METADATA_SCHEMA_VERSION,
|
||||
find_metadata_sidecar_path,
|
||||
get_filename_from_path,
|
||||
normalize_metadata_file_path,
|
||||
read_merged_model_metadata,
|
||||
)
|
||||
from ..resolver import normalize_sha256
|
||||
@@ -116,8 +117,7 @@ def _coerce_size(value: Any) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
def _normalise_metadata_file_path(path_value: str) -> str:
|
||||
return str(path_value or "").replace(os.sep, "/")
|
||||
_normalise_metadata_file_path = normalize_metadata_file_path
|
||||
|
||||
|
||||
def _resolve_lora_manager_model_type(category: str, source_type: Any = "") -> str:
|
||||
|
||||
@@ -31,6 +31,7 @@ from .path_utils import (
|
||||
find_external_metadata_sidecar_path,
|
||||
get_filename_from_path,
|
||||
get_model_resolver_sidecar_path,
|
||||
normalize_metadata_file_path,
|
||||
read_json_safe,
|
||||
read_safetensors_header,
|
||||
write_json_atomic,
|
||||
@@ -255,8 +256,7 @@ def _merge_unique_strings(*values: Any) -> List[str]:
|
||||
return result
|
||||
|
||||
|
||||
def _normalise_metadata_file_path(path_value: str) -> str:
|
||||
return str(path_value or "").replace(os.sep, "/")
|
||||
_normalise_metadata_file_path = normalize_metadata_file_path
|
||||
|
||||
|
||||
def _model_type_for_category(category: str) -> str:
|
||||
|
||||
@@ -55,6 +55,18 @@ def get_path_identity(path: str) -> str:
|
||||
return os.path.normcase(os.path.abspath(path))
|
||||
|
||||
|
||||
def normalize_absolute_path(path_value: Any, path_module=os.path) -> str:
|
||||
"""Return an absolute, normalized and symlink-resolved path."""
|
||||
return path_module.realpath(
|
||||
path_module.abspath(path_module.normpath(str(path_value)))
|
||||
)
|
||||
|
||||
|
||||
def normalize_metadata_file_path(path_value: Any) -> str:
|
||||
"""Normalize metadata paths to portable forward-slash separators."""
|
||||
return str(path_value or "").replace(os.sep, "/")
|
||||
|
||||
|
||||
def get_path_abs(path_value: Any) -> str:
|
||||
"""Return absolute path safely, handling OSError/ValueError."""
|
||||
try:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""CivitAI model search service."""
|
||||
|
||||
from .. import path_utils
|
||||
from ..routes.context import RouteContext
|
||||
from ..sources.common import is_remote_link_marked_dead
|
||||
from .model_utils import CivitAISearchDependencies, ModelServiceDependencies
|
||||
@@ -99,8 +100,9 @@ class CivitAISearchService(ModelServiceDependencies):
|
||||
file_path = find_local_file_path(filename, category)
|
||||
|
||||
if file_path:
|
||||
file_path = _os.path.realpath(
|
||||
_os.path.abspath(_os.path.normpath(str(file_path)))
|
||||
file_path = path_utils.normalize_absolute_path(
|
||||
file_path,
|
||||
path_module=_os.path,
|
||||
)
|
||||
if not is_path_in_configured_model_roots(file_path):
|
||||
if resolved_path:
|
||||
|
||||
@@ -71,8 +71,9 @@ class HashService:
|
||||
return self.extension.logger
|
||||
|
||||
def _normalize_path(self, path):
|
||||
return self.os.path.realpath(
|
||||
self.os.path.abspath(self.os.path.normpath(str(path)))
|
||||
return path_utils.normalize_absolute_path(
|
||||
path,
|
||||
path_module=self.os.path,
|
||||
)
|
||||
|
||||
async def local_model_hashes(self, request):
|
||||
|
||||
@@ -5,6 +5,7 @@ from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from core.download.api import context as downloader
|
||||
from core.path_utils import normalize_metadata_file_path
|
||||
|
||||
|
||||
class DownloaderBoundaryTests(unittest.TestCase):
|
||||
@@ -60,6 +61,7 @@ class DownloaderBoundaryTests(unittest.TestCase):
|
||||
self.assertEqual(12, downloader._coerce_size("12.9"))
|
||||
self.assertEqual(0, downloader._coerce_size("not-a-size"))
|
||||
self.assertEqual("models/subfolder", downloader._normalise_metadata_file_path("models\\subfolder"))
|
||||
self.assertEqual("models/subfolder", normalize_metadata_file_path("models\\subfolder"))
|
||||
|
||||
def test_metadata_source_and_model_type_helpers_cover_provider_variants(self):
|
||||
self.assertEqual(
|
||||
|
||||
@@ -8,7 +8,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
||||
import pytest
|
||||
from aiohttp import web
|
||||
|
||||
from core.path_utils import HashCalculationCancelled
|
||||
from core.path_utils import HashCalculationCancelled, normalize_absolute_path
|
||||
from core.routes.context import RouteContext
|
||||
from core.routes.hashes import register_hash_routes
|
||||
from core.services.hash_service import HashService
|
||||
@@ -134,6 +134,21 @@ async def test_local_model_hashes_uses_model_path_and_returns_metadata():
|
||||
)
|
||||
|
||||
|
||||
def test_hash_service_path_normalization_uses_shared_helper_and_injected_path_module():
|
||||
_, values = _build_hash_routes()
|
||||
service = HashService(RouteContext(values))
|
||||
model_path = "models/checkpoints/../loras/model.safetensors"
|
||||
|
||||
with patch(
|
||||
"core.path_utils.normalize_absolute_path",
|
||||
wraps=normalize_absolute_path,
|
||||
) as normalize_path:
|
||||
result = service._normalize_path(model_path)
|
||||
|
||||
assert result == normalize_absolute_path(model_path)
|
||||
normalize_path.assert_called_once_with(model_path, path_module=os.path)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_hash_routes_validate_local_metadata_and_preview_paths():
|
||||
handlers, values = _build_hash_routes()
|
||||
|
||||
Reference in New Issue
Block a user