2026-06-15 16:48:37 +08:00
|
|
|
import logging
|
|
|
|
|
import sys
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
2026-06-15 15:53:01 +08:00
|
|
|
SUPPORTED_IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".webp"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_supported_image(path):
|
|
|
|
|
return path.suffix.lower() in SUPPORTED_IMAGE_EXTENSIONS
|
2026-06-15 16:48:37 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
# Path helpers
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
def get_app_dir():
|
|
|
|
|
"""Return the application root directory as a Path.
|
|
|
|
|
|
|
|
|
|
PyInstaller onedir: directory that contains the .exe.
|
|
|
|
|
Development: project root (three levels above this file:
|
|
|
|
|
src/services/file_service.py -> src/services -> src -> project root).
|
|
|
|
|
"""
|
|
|
|
|
if getattr(sys, "frozen", False):
|
|
|
|
|
return Path(sys.executable).resolve().parent
|
|
|
|
|
return Path(__file__).resolve().parent.parent.parent
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_resource_path(relative_path):
|
|
|
|
|
"""Return absolute Path for a file under <app_dir>/resources/."""
|
|
|
|
|
return get_app_dir() / "resources" / relative_path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_config_path(relative_path):
|
|
|
|
|
"""Return absolute Path for a file under <app_dir>/config/."""
|
|
|
|
|
return get_app_dir() / "config" / relative_path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_log_dir():
|
|
|
|
|
"""Return <app_dir>/logs/ as a Path, creating the directory if absent."""
|
|
|
|
|
d = get_app_dir() / "logs"
|
|
|
|
|
d.mkdir(exist_ok=True)
|
|
|
|
|
return d
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_output_dir():
|
|
|
|
|
"""Return <app_dir>/output/ as a Path, creating the directory if absent."""
|
|
|
|
|
d = get_app_dir() / "output"
|
|
|
|
|
d.mkdir(exist_ok=True)
|
|
|
|
|
return d
|