mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-05-12 04:27:50 -03:00
feat: normalize tags to lowercase for Windows compatibility, see #637
Convert all tags to lowercase in tag processing logic to prevent case sensitivity issues on Windows filesystems. This ensures consistent tag matching and prevents duplicate tags with different cases from being created. Changes include: - TagUpdateService now converts tags to lowercase before comparison - Utils function converts model tags to lowercase before priority resolution - Test cases updated to reflect lowercase tag expectations
This commit is contained in:
@@ -240,7 +240,7 @@ def test_download_coordinator_emits_progress() -> None:
|
||||
|
||||
def test_tag_update_service_adds_unique_tags(tmp_path: Path) -> None:
|
||||
metadata_path = tmp_path / "model.metadata.json"
|
||||
metadata_path.write_text(json.dumps({"tags": ["Existing"]}))
|
||||
metadata_path.write_text(json.dumps({"tags": ["existing"]}))
|
||||
|
||||
async def loader(path: str) -> Dict[str, Any]:
|
||||
return json.loads(Path(path).read_text())
|
||||
@@ -258,12 +258,12 @@ def test_tag_update_service_adds_unique_tags(tmp_path: Path) -> None:
|
||||
tags = asyncio.run(
|
||||
service.add_tags(
|
||||
file_path=str(tmp_path / "model.safetensors"),
|
||||
new_tags=["New", "existing"],
|
||||
new_tags=["new", "existing"],
|
||||
metadata_loader=loader,
|
||||
update_cache=update_cache,
|
||||
)
|
||||
)
|
||||
|
||||
assert tags == ["Existing", "New"]
|
||||
assert tags == ["existing", "new"]
|
||||
assert manager.saved
|
||||
assert cache_updates
|
||||
|
||||
96
tests/services/test_tag_case_sensitivity.py
Normal file
96
tests/services/test_tag_case_sensitivity.py
Normal file
@@ -0,0 +1,96 @@
|
||||
"""Tests for tag case sensitivity handling to prevent issues on Windows."""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict
|
||||
|
||||
import pytest
|
||||
|
||||
from py.services.tag_update_service import TagUpdateService
|
||||
|
||||
|
||||
class RecordingMetadataManager:
|
||||
def __init__(self) -> None:
|
||||
self.saved: list[tuple[str, Dict[str, Any]]] = []
|
||||
|
||||
async def save_metadata(self, path: str, metadata: Dict[str, Any]) -> bool:
|
||||
self.saved.append((path, json.loads(json.dumps(metadata))))
|
||||
return True
|
||||
|
||||
|
||||
class DummyProvider:
|
||||
async def __call__(self, path: str) -> Dict[str, Any]:
|
||||
return {"tags": []}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tag_update_service_handles_case_insensitive_tags(tmp_path: Path) -> None:
|
||||
"""Test that tag update service treats tags case-insensitively."""
|
||||
metadata_path = tmp_path / "model.metadata.json"
|
||||
metadata_path.write_text(json.dumps({"tags": ["test"]}))
|
||||
|
||||
async def loader(path: str) -> Dict[str, Any]:
|
||||
return json.loads(Path(path).read_text())
|
||||
|
||||
manager = RecordingMetadataManager()
|
||||
service = TagUpdateService(metadata_manager=manager)
|
||||
|
||||
cache_updates: list[Dict[str, Any]] = []
|
||||
|
||||
async def update_cache(original: str, new: str, metadata: Dict[str, Any]) -> bool:
|
||||
cache_updates.append(metadata)
|
||||
return True
|
||||
|
||||
# Try to add "Test" (different case) - should not be added since "test" already exists
|
||||
tags = await service.add_tags(
|
||||
file_path=str(tmp_path / "model.safetensors"),
|
||||
new_tags=["Test"],
|
||||
metadata_loader=loader,
|
||||
update_cache=update_cache,
|
||||
)
|
||||
|
||||
# Should still only have "test" (lowercase) in the tags
|
||||
assert tags == ["test"]
|
||||
assert len(manager.saved) == 1
|
||||
saved_metadata = manager.saved[0][1]
|
||||
assert saved_metadata["tags"] == ["test"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tag_update_service_adds_new_tags_in_lowercase(tmp_path: Path) -> None:
|
||||
"""Test that new tags are stored in lowercase."""
|
||||
metadata_path = tmp_path / "model.metadata.json"
|
||||
metadata_path.write_text(json.dumps({"tags": ["existing"]}))
|
||||
|
||||
async def loader(path: str) -> Dict[str, Any]:
|
||||
return json.loads(Path(path).read_text())
|
||||
|
||||
manager = RecordingMetadataManager()
|
||||
service = TagUpdateService(metadata_manager=manager)
|
||||
|
||||
cache_updates: list[Dict[str, Any]] = []
|
||||
|
||||
async def update_cache(original: str, new: str, metadata: Dict[str, Any]) -> bool:
|
||||
cache_updates.append(metadata)
|
||||
return True
|
||||
|
||||
# Add new tags with mixed case
|
||||
tags = await service.add_tags(
|
||||
file_path=str(tmp_path / "model.safetensors"),
|
||||
new_tags=["NewTag", "ANOTHER_TAG"],
|
||||
metadata_loader=loader,
|
||||
update_cache=update_cache,
|
||||
)
|
||||
|
||||
# New tags should be stored in lowercase
|
||||
assert "existing" in tags
|
||||
assert "newtag" in tags
|
||||
assert "another_tag" in tags
|
||||
assert len(manager.saved) == 1
|
||||
saved_metadata = manager.saved[0][1]
|
||||
assert "newtag" in saved_metadata["tags"]
|
||||
assert "another_tag" in saved_metadata["tags"]
|
||||
# Ensure all tags are lowercase
|
||||
for tag in saved_metadata["tags"]:
|
||||
assert tag == tag.lower()
|
||||
Reference in New Issue
Block a user