lkjlkj
This commit is contained in:
@@ -11,7 +11,7 @@ from typing import Any, Dict, List, Optional, Tuple
|
||||
from SYS.logger import debug, log
|
||||
from SYS.utils import sha256_file
|
||||
|
||||
from Store._base import StoreBackend
|
||||
from Store._base import Store
|
||||
|
||||
|
||||
def _normalize_hash(value: Any) -> Optional[str]:
|
||||
@@ -30,7 +30,7 @@ def _resolve_file_hash(db_hash: Optional[str], file_path: Path) -> Optional[str]
|
||||
return _normalize_hash(file_path.stem)
|
||||
|
||||
|
||||
class Folder(StoreBackend):
|
||||
class Folder(Store):
|
||||
""""""
|
||||
# Track which locations have already been migrated to avoid repeated migrations
|
||||
_migrated_locations = set()
|
||||
@@ -243,7 +243,7 @@ class Folder(StoreBackend):
|
||||
Args:
|
||||
file_path: Path to the file to add
|
||||
move: If True, move file instead of copy (default: False)
|
||||
tags: Optional list of tags to add
|
||||
tag: Optional list of tag values to add
|
||||
url: Optional list of url to associate with the file
|
||||
title: Optional title (will be added as 'title:value' tag)
|
||||
|
||||
@@ -251,15 +251,15 @@ class Folder(StoreBackend):
|
||||
File hash (SHA256 hex string) as identifier
|
||||
"""
|
||||
move_file = bool(kwargs.get("move"))
|
||||
tags = kwargs.get("tags", [])
|
||||
tag_list = kwargs.get("tag", [])
|
||||
url = kwargs.get("url", [])
|
||||
title = kwargs.get("title")
|
||||
|
||||
# Extract title from tags if not explicitly provided
|
||||
if not title:
|
||||
for tag in tags:
|
||||
if isinstance(tag, str) and tag.lower().startswith("title:"):
|
||||
title = tag.split(":", 1)[1].strip()
|
||||
for candidate in tag_list:
|
||||
if isinstance(candidate, str) and candidate.lower().startswith("title:"):
|
||||
title = candidate.split(":", 1)[1].strip()
|
||||
break
|
||||
|
||||
# Fallback to filename if no title
|
||||
@@ -268,8 +268,8 @@ class Folder(StoreBackend):
|
||||
|
||||
# Ensure title is in tags
|
||||
title_tag = f"title:{title}"
|
||||
if not any(str(tag).lower().startswith("title:") for tag in tags):
|
||||
tags = [title_tag] + list(tags)
|
||||
if not any(str(candidate).lower().startswith("title:") for candidate in tag_list):
|
||||
tag_list = [title_tag] + list(tag_list)
|
||||
|
||||
try:
|
||||
file_hash = sha256_file(file_path)
|
||||
@@ -290,8 +290,8 @@ class Folder(StoreBackend):
|
||||
file=sys.stderr,
|
||||
)
|
||||
# Still add tags and url if provided
|
||||
if tags:
|
||||
self.add_tag(file_hash, tags)
|
||||
if tag_list:
|
||||
self.add_tag(file_hash, tag_list)
|
||||
if url:
|
||||
self.add_url(file_hash, url)
|
||||
return file_hash
|
||||
@@ -316,8 +316,8 @@ class Folder(StoreBackend):
|
||||
})
|
||||
|
||||
# Add tags if provided
|
||||
if tags:
|
||||
self.add_tag(file_hash, tags)
|
||||
if tag_list:
|
||||
self.add_tag(file_hash, tag_list)
|
||||
|
||||
# Add url if provided
|
||||
if url:
|
||||
@@ -330,7 +330,7 @@ class Folder(StoreBackend):
|
||||
log(f"❌ Local storage failed: {exc}", file=sys.stderr)
|
||||
raise
|
||||
|
||||
def search_store(self, query: str, **kwargs: Any) -> list[Dict[str, Any]]:
|
||||
def search(self, query: str, **kwargs: Any) -> list[Dict[str, Any]]:
|
||||
"""Search local database for files by title tag or filename."""
|
||||
from fnmatch import fnmatch
|
||||
from API.folder import DatabaseAPI
|
||||
@@ -685,9 +685,6 @@ class Folder(StoreBackend):
|
||||
log(f"❌ Local search failed: {exc}", file=sys.stderr)
|
||||
raise
|
||||
|
||||
def search(self, query: str, **kwargs: Any) -> list[Dict[str, Any]]:
|
||||
"""Alias for search_file to match the interface expected by FileStorage."""
|
||||
return self.search_store(query, **kwargs)
|
||||
|
||||
def _resolve_library_root(self, file_path: Path, config: Dict[str, Any]) -> Optional[Path]:
|
||||
"""Return the library root containing medios-macina.db.
|
||||
|
||||
@@ -8,10 +8,10 @@ from typing import Any, Dict, List, Optional, Tuple
|
||||
from SYS.logger import debug, log
|
||||
from SYS.utils_constant import mime_maps
|
||||
|
||||
from Store._base import StoreBackend
|
||||
from Store._base import Store
|
||||
|
||||
|
||||
class HydrusNetwork(StoreBackend):
|
||||
class HydrusNetwork(Store):
|
||||
"""File storage backend for Hydrus client.
|
||||
|
||||
Each instance represents a specific Hydrus client connection.
|
||||
@@ -26,7 +26,7 @@ class HydrusNetwork(StoreBackend):
|
||||
api_key: Hydrus Client API access key
|
||||
url: Hydrus client URL (e.g., 'http://192.168.1.230:45869')
|
||||
"""
|
||||
from API.HydrusNetwork import HydrusClient
|
||||
from API.HydrusNetwork import HydrusNetwork as HydrusClient
|
||||
|
||||
self._instance_name = instance_name
|
||||
self._api_key = api_key
|
||||
@@ -45,7 +45,7 @@ class HydrusNetwork(StoreBackend):
|
||||
|
||||
Args:
|
||||
file_path: Path to the file to upload
|
||||
tags: Optional list of tags to add
|
||||
tag: Optional list of tag values to add
|
||||
url: Optional list of url to associate with the file
|
||||
title: Optional title (will be added as 'title:value' tag)
|
||||
|
||||
@@ -57,15 +57,15 @@ class HydrusNetwork(StoreBackend):
|
||||
"""
|
||||
from SYS.utils import sha256_file
|
||||
|
||||
tags = kwargs.get("tags", [])
|
||||
tag_list = kwargs.get("tag", [])
|
||||
url = kwargs.get("url", [])
|
||||
title = kwargs.get("title")
|
||||
|
||||
# Add title to tags if provided and not already present
|
||||
if title:
|
||||
title_tag = f"title:{title}"
|
||||
if not any(str(tag).lower().startswith("title:") for tag in tags):
|
||||
tags = [title_tag] + list(tags)
|
||||
if not any(str(candidate).lower().startswith("title:") for candidate in tag_list):
|
||||
tag_list = [title_tag] + list(tag_list)
|
||||
|
||||
try:
|
||||
# Compute file hash
|
||||
@@ -113,7 +113,7 @@ class HydrusNetwork(StoreBackend):
|
||||
log(f"Hydrus: {file_hash}", file=sys.stderr)
|
||||
|
||||
# Add tags if provided (both for new and existing files)
|
||||
if tags:
|
||||
if tag_list:
|
||||
try:
|
||||
# Use default tag service
|
||||
service_name = "my tags"
|
||||
@@ -121,8 +121,8 @@ class HydrusNetwork(StoreBackend):
|
||||
service_name = "my tags"
|
||||
|
||||
try:
|
||||
debug(f"Adding {len(tags)} tag(s) to Hydrus: {tags}")
|
||||
client.add_tags(file_hash, tags, service_name)
|
||||
debug(f"Adding {len(tag_list)} tag(s) to Hydrus: {tag_list}")
|
||||
client.add_tag(file_hash, tag_list, service_name)
|
||||
log(f"Tags added via '{service_name}'", file=sys.stderr)
|
||||
except Exception as exc:
|
||||
log(f"⚠️ Failed to add tags: {exc}", file=sys.stderr)
|
||||
@@ -144,7 +144,7 @@ class HydrusNetwork(StoreBackend):
|
||||
log(f"❌ Hydrus upload failed: {exc}", file=sys.stderr)
|
||||
raise
|
||||
|
||||
def search_store(self, query: str, **kwargs: Any) -> list[Dict[str, Any]]:
|
||||
def search(self, query: str, **kwargs: Any) -> list[Dict[str, Any]]:
|
||||
"""Search Hydrus database for files matching query.
|
||||
|
||||
Args:
|
||||
@@ -290,7 +290,7 @@ class HydrusNetwork(StoreBackend):
|
||||
"size": size,
|
||||
"size_bytes": size,
|
||||
"store": self._instance_name,
|
||||
"tags": all_tags,
|
||||
"tag": all_tags,
|
||||
"file_id": file_id,
|
||||
"mime": mime_type,
|
||||
"ext": ext,
|
||||
@@ -323,7 +323,7 @@ class HydrusNetwork(StoreBackend):
|
||||
"size": size,
|
||||
"size_bytes": size,
|
||||
"store": self._instance_name,
|
||||
"tags": all_tags,
|
||||
"tag": all_tags,
|
||||
"file_id": file_id,
|
||||
"mime": mime_type,
|
||||
"ext": ext,
|
||||
@@ -488,7 +488,7 @@ class HydrusNetwork(StoreBackend):
|
||||
tag_list = list(tags) if isinstance(tags, (list, tuple)) else [str(tags)]
|
||||
if not tag_list:
|
||||
return False
|
||||
client.add_tags(file_identifier, tag_list, service_name)
|
||||
client.add_tag(file_identifier, tag_list, service_name)
|
||||
return True
|
||||
except Exception as exc:
|
||||
debug(f"Hydrus add_tag failed: {exc}")
|
||||
@@ -506,7 +506,7 @@ class HydrusNetwork(StoreBackend):
|
||||
tag_list = list(tags) if isinstance(tags, (list, tuple)) else [str(tags)]
|
||||
if not tag_list:
|
||||
return False
|
||||
client.delete_tags(file_identifier, tag_list, service_name)
|
||||
client.delete_tag(file_identifier, tag_list, service_name)
|
||||
return True
|
||||
except Exception as exc:
|
||||
debug(f"Hydrus delete_tag failed: {exc}")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from Store._base import StoreBackend
|
||||
from Store._base import Store as BaseStore
|
||||
from Store.registry import Store
|
||||
|
||||
__all__ = [
|
||||
"StoreBackend",
|
||||
"Store",
|
||||
"BaseStore",
|
||||
]
|
||||
|
||||
@@ -10,7 +10,7 @@ from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
|
||||
class StoreBackend(ABC):
|
||||
class Store(ABC):
|
||||
@abstractmethod
|
||||
def add_file(self, file_path: Path, **kwargs: Any) -> str:
|
||||
raise NotImplementedError
|
||||
@@ -19,7 +19,7 @@ class StoreBackend(ABC):
|
||||
def name(self) -> str:
|
||||
raise NotImplementedError
|
||||
|
||||
def search_store(self, query: str, **kwargs: Any) -> list[Dict[str, Any]]:
|
||||
def search(self, query: str, **kwargs: Any) -> list[Dict[str, Any]]:
|
||||
raise NotImplementedError(f"{self.name()} backend does not support searching")
|
||||
|
||||
@abstractmethod
|
||||
|
||||
@@ -25,7 +25,7 @@ from typing import Any, Dict, Optional
|
||||
|
||||
from SYS.logger import debug
|
||||
|
||||
from Store._base import StoreBackend
|
||||
from Store._base import Store as BaseStore
|
||||
from Store.Folder import Folder
|
||||
from Store.HydrusNetwork import HydrusNetwork
|
||||
|
||||
@@ -34,7 +34,7 @@ class Store:
|
||||
def __init__(self, config: Optional[Dict[str, Any]] = None, suppress_debug: bool = False) -> None:
|
||||
self._config = config or {}
|
||||
self._suppress_debug = suppress_debug
|
||||
self._backends: Dict[str, StoreBackend] = {}
|
||||
self._backends: Dict[str, BaseStore] = {}
|
||||
self._load_backends()
|
||||
|
||||
def _load_backends(self) -> None:
|
||||
@@ -86,11 +86,11 @@ class Store:
|
||||
def list_searchable_backends(self) -> list[str]:
|
||||
searchable: list[str] = []
|
||||
for name, backend in self._backends.items():
|
||||
if type(backend).search_store is not StoreBackend.search_store:
|
||||
if type(backend).search is not BaseStore.search:
|
||||
searchable.append(name)
|
||||
return sorted(searchable)
|
||||
|
||||
def __getitem__(self, backend_name: str) -> StoreBackend:
|
||||
def __getitem__(self, backend_name: str) -> BaseStore:
|
||||
if backend_name not in self._backends:
|
||||
raise KeyError(f"Unknown store backend: {backend_name}. Available: {list(self._backends.keys())}")
|
||||
return self._backends[backend_name]
|
||||
|
||||
Reference in New Issue
Block a user