Merge pull request #113 from ComfyAssets/fix/custom-scan-directory-108
fix: respect custom image scan directory setting
This commit is contained in:
+30
-2
@@ -448,8 +448,15 @@ class PromptManagerAPI(
|
||||
def _find_comfyui_output_dir(self):
|
||||
"""Locate the ComfyUI output directory using multiple detection strategies.
|
||||
|
||||
Results are cached after first successful lookup since the output
|
||||
directory does not change during runtime.
|
||||
Checks in order:
|
||||
1. User-configured directory (GalleryConfig.MONITORING_DIRECTORIES)
|
||||
2. Upward filesystem search for ComfyUI markers
|
||||
3. Common installation path patterns
|
||||
4. Common ComfyUI installation locations
|
||||
|
||||
Results are cached after first successful lookup. The cache is
|
||||
invalidated when the user changes the configured directory via
|
||||
save_settings().
|
||||
|
||||
Returns:
|
||||
str or None: Absolute path to ComfyUI output directory, or None
|
||||
@@ -458,6 +465,27 @@ class PromptManagerAPI(
|
||||
if self._cached_output_dir is not None:
|
||||
return self._cached_output_dir
|
||||
|
||||
# Method 0: Check user-configured directory first
|
||||
try:
|
||||
from ..config import GalleryConfig
|
||||
|
||||
if GalleryConfig.MONITORING_DIRECTORIES:
|
||||
configured_dir = Path(GalleryConfig.MONITORING_DIRECTORIES[0]).resolve()
|
||||
if configured_dir.exists() and configured_dir.is_dir():
|
||||
self.logger.info(
|
||||
f"Using configured monitoring directory: {configured_dir}"
|
||||
)
|
||||
self._cached_output_dir = str(configured_dir)
|
||||
return self._cached_output_dir
|
||||
else:
|
||||
self.logger.warning(
|
||||
f"Configured directory does not exist: {GalleryConfig.MONITORING_DIRECTORIES[0]}"
|
||||
)
|
||||
except ImportError:
|
||||
self.logger.debug(
|
||||
"GalleryConfig not available, skipping configured directory check"
|
||||
)
|
||||
|
||||
current_file = Path(__file__).resolve()
|
||||
self.logger.debug(f"Starting ComfyUI output search from: {current_file}")
|
||||
|
||||
|
||||
@@ -448,6 +448,10 @@ class AdminRoutesMixin:
|
||||
GalleryConfig.MONITORING_DIRECTORIES = [new_path]
|
||||
else:
|
||||
GalleryConfig.MONITORING_DIRECTORIES = []
|
||||
# Invalidate caches so next lookup uses new config
|
||||
self._cached_output_dir = None
|
||||
self._gallery_cache = None
|
||||
self._gallery_cache_time = 0
|
||||
restart_required = True
|
||||
|
||||
# Save to config file for persistence
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "promptmanager"
|
||||
description = "A powerful ComfyUI custom node that extends the standard text encoder with persistent prompt storage, advanced search capabilities, and an automatic image gallery system using SQLite."
|
||||
version = "3.0.36"
|
||||
version = "3.0.37"
|
||||
license = {file = "LICENSE"}
|
||||
dependencies = ["# Core dependencies for PromptManager", "# Note: Most dependencies are already included with ComfyUI", "# Already included with Python standard library:", "# - sqlite3", "# - hashlib", "# - json", "# - datetime", "# - os", "# - typing", "# - threading", "# - uuid", "# Required for gallery functionality:", "watchdog>=2.1.0 # For file system monitoring", "Pillow>=8.0.0 # For image metadata extraction (usually included with ComfyUI)", "# Optional dependencies for enhanced search functionality:", "# fuzzywuzzy[speedup]>=0.18.0 # For fuzzy string matching (optional)", "# sqlalchemy>=1.4.0 # For advanced ORM features (optional)", "# Development dependencies (optional):", "# pytest>=6.0.0 # For running tests", "# black>=22.0.0 # For code formatting", "# flake8>=4.0.0 # For linting", "# mypy>=0.910 # For type checking"]
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
"""
|
||||
Tests for _find_comfyui_output_dir() — verifies that user-configured
|
||||
directories take priority over auto-detection, and that the cache is
|
||||
invalidated when the setting changes.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
# Mock ComfyUI's server module before importing anything that touches config
|
||||
_mock_server = MagicMock()
|
||||
_mock_server.PromptServer.instance.routes = MagicMock()
|
||||
sys.modules["server"] = _mock_server
|
||||
|
||||
from py.api import PromptManagerAPI
|
||||
from py.config import GalleryConfig
|
||||
|
||||
|
||||
class TestFindComfyuiOutputDir(unittest.TestCase):
|
||||
"""Test _find_comfyui_output_dir() respects user-configured directories."""
|
||||
|
||||
def setUp(self):
|
||||
self.api = PromptManagerAPI()
|
||||
self.api._cached_output_dir = None
|
||||
self._orig_dirs = list(GalleryConfig.MONITORING_DIRECTORIES)
|
||||
|
||||
def tearDown(self):
|
||||
GalleryConfig.MONITORING_DIRECTORIES = self._orig_dirs
|
||||
|
||||
def test_configured_directory_takes_priority(self):
|
||||
"""When a valid directory is configured, it should be used instead of auto-detect."""
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
GalleryConfig.MONITORING_DIRECTORIES = [tmpdir]
|
||||
self.api._cached_output_dir = None
|
||||
|
||||
result = self.api._find_comfyui_output_dir()
|
||||
|
||||
self.assertEqual(result, str(Path(tmpdir).resolve()))
|
||||
|
||||
def test_nonexistent_configured_directory_falls_through(self):
|
||||
"""When the configured directory doesn't exist, fall back to auto-detection."""
|
||||
GalleryConfig.MONITORING_DIRECTORIES = ["/nonexistent/fake/path/output"]
|
||||
self.api._cached_output_dir = None
|
||||
|
||||
# Should not return the nonexistent path — will either find
|
||||
# ComfyUI output via auto-detect or return None
|
||||
result = self.api._find_comfyui_output_dir()
|
||||
|
||||
self.assertNotEqual(result, "/nonexistent/fake/path/output")
|
||||
|
||||
def test_empty_config_uses_auto_detection(self):
|
||||
"""When MONITORING_DIRECTORIES is empty, auto-detection should be used."""
|
||||
GalleryConfig.MONITORING_DIRECTORIES = []
|
||||
self.api._cached_output_dir = None
|
||||
|
||||
# Should not raise — auto-detection may or may not find a dir
|
||||
result = self.api._find_comfyui_output_dir()
|
||||
# Result is either a valid path or None
|
||||
if result is not None:
|
||||
self.assertTrue(Path(result).is_dir())
|
||||
|
||||
def test_cache_returns_same_value(self):
|
||||
"""After first lookup, cached value should be returned."""
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
GalleryConfig.MONITORING_DIRECTORIES = [tmpdir]
|
||||
self.api._cached_output_dir = None
|
||||
|
||||
result1 = self.api._find_comfyui_output_dir()
|
||||
# Change config — should NOT affect result because of cache
|
||||
GalleryConfig.MONITORING_DIRECTORIES = ["/some/other/path"]
|
||||
result2 = self.api._find_comfyui_output_dir()
|
||||
|
||||
self.assertEqual(result1, result2)
|
||||
|
||||
def test_cache_invalidation_picks_up_new_directory(self):
|
||||
"""After clearing the cache, _find_comfyui_output_dir should use new config."""
|
||||
with tempfile.TemporaryDirectory() as tmpdir1:
|
||||
with tempfile.TemporaryDirectory() as tmpdir2:
|
||||
GalleryConfig.MONITORING_DIRECTORIES = [tmpdir1]
|
||||
self.api._cached_output_dir = None
|
||||
|
||||
result1 = self.api._find_comfyui_output_dir()
|
||||
self.assertEqual(result1, str(Path(tmpdir1).resolve()))
|
||||
|
||||
# Simulate what save_settings does: update config + invalidate cache
|
||||
GalleryConfig.MONITORING_DIRECTORIES = [tmpdir2]
|
||||
self.api._cached_output_dir = None
|
||||
|
||||
result2 = self.api._find_comfyui_output_dir()
|
||||
self.assertEqual(result2, str(Path(tmpdir2).resolve()))
|
||||
|
||||
def test_configured_directory_is_resolved(self):
|
||||
"""Configured paths with symlinks or .. should be resolved to absolute."""
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
# Use a relative-ish path with ..
|
||||
parent = str(Path(tmpdir).parent)
|
||||
basename = Path(tmpdir).name
|
||||
dotdot_path = os.path.join(parent, ".", basename)
|
||||
|
||||
GalleryConfig.MONITORING_DIRECTORIES = [dotdot_path]
|
||||
self.api._cached_output_dir = None
|
||||
|
||||
result = self.api._find_comfyui_output_dir()
|
||||
|
||||
self.assertEqual(result, str(Path(tmpdir).resolve()))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user