fix: get_export_folders respects scan_export filter
Ghost folders (scan-export-only) no longer appear in training dropdowns. Also filters out 0-clip folders from get_training_stats. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+42
-7
@@ -291,7 +291,35 @@ class ProcessedDB:
|
|||||||
).fetchall()
|
).fetchall()
|
||||||
return [r[0] for r in rows]
|
return [r[0] for r in rows]
|
||||||
|
|
||||||
def get_export_folders(self, profile: str = "default") -> list[str]:
|
def get_max_counter(self, folder: str, name: str) -> int:
|
||||||
|
"""Return the highest counter N found in output_paths matching folder/name_NNN*.
|
||||||
|
|
||||||
|
Parses the group directory component (e.g. 'clip_035') from stored
|
||||||
|
output_path values. Returns 0 if no matches exist.
|
||||||
|
"""
|
||||||
|
if not self._enabled:
|
||||||
|
return 0
|
||||||
|
prefix = os.path.join(folder, name + "_")
|
||||||
|
rows = self._con.execute(
|
||||||
|
"SELECT DISTINCT output_path FROM processed"
|
||||||
|
" WHERE output_path LIKE ?",
|
||||||
|
(prefix + "%",),
|
||||||
|
).fetchall()
|
||||||
|
max_n = 0
|
||||||
|
for (op,) in rows:
|
||||||
|
# output_path: .../folder/name_NNN/name_NNN_sub.ext
|
||||||
|
parent = os.path.basename(os.path.dirname(op))
|
||||||
|
# parent should be "name_NNN"
|
||||||
|
parts = parent.rsplit("_", 1)
|
||||||
|
if len(parts) == 2:
|
||||||
|
try:
|
||||||
|
max_n = max(max_n, int(parts[1]))
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
return max_n
|
||||||
|
|
||||||
|
def get_export_folders(self, profile: str = "default",
|
||||||
|
include_scan_exports: bool = False) -> list[str]:
|
||||||
"""Return distinct export folder names found in output_paths for a profile.
|
"""Return distinct export folder names found in output_paths for a profile.
|
||||||
|
|
||||||
Export paths follow the structure:
|
Export paths follow the structure:
|
||||||
@@ -301,10 +329,17 @@ class ProcessedDB:
|
|||||||
"""
|
"""
|
||||||
if not self._enabled:
|
if not self._enabled:
|
||||||
return []
|
return []
|
||||||
rows = self._con.execute(
|
if include_scan_exports:
|
||||||
"SELECT DISTINCT output_path FROM processed WHERE profile = ?",
|
rows = self._con.execute(
|
||||||
(profile,),
|
"SELECT DISTINCT output_path FROM processed WHERE profile = ?",
|
||||||
).fetchall()
|
(profile,),
|
||||||
|
).fetchall()
|
||||||
|
else:
|
||||||
|
rows = self._con.execute(
|
||||||
|
"SELECT DISTINCT output_path FROM processed"
|
||||||
|
" WHERE profile = ? AND scan_export = 0",
|
||||||
|
(profile,),
|
||||||
|
).fetchall()
|
||||||
folder_names: set[str] = set()
|
folder_names: set[str] = set()
|
||||||
for (op,) in rows:
|
for (op,) in rows:
|
||||||
grandparent = os.path.basename(os.path.dirname(os.path.dirname(op)))
|
grandparent = os.path.basename(os.path.dirname(os.path.dirname(op)))
|
||||||
@@ -429,7 +464,7 @@ class ProcessedDB:
|
|||||||
" WHERE profile = ? AND scan_export = 0",
|
" WHERE profile = ? AND scan_export = 0",
|
||||||
(profile,),
|
(profile,),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
folders = self.get_export_folders(profile)
|
folders = self.get_export_folders(profile, include_scan_exports=include_scan_exports)
|
||||||
stats: dict[str, dict] = {}
|
stats: dict[str, dict] = {}
|
||||||
for folder_name in folders:
|
for folder_name in folders:
|
||||||
videos: set[str] = set()
|
videos: set[str] = set()
|
||||||
@@ -440,7 +475,7 @@ class ProcessedDB:
|
|||||||
videos.add(fn)
|
videos.add(fn)
|
||||||
clips += 1
|
clips += 1
|
||||||
stats[folder_name] = {"videos": len(videos), "clips": clips}
|
stats[folder_name] = {"videos": len(videos), "clips": clips}
|
||||||
return stats
|
return {k: v for k, v in stats.items() if v["clips"] > 0}
|
||||||
|
|
||||||
# ── Scan results ─────────────────────────────────────────────
|
# ── Scan results ─────────────────────────────────────────────
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
from core.db import ProcessedDB
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_folders_excludes_scan_exports():
|
||||||
|
"""Scan-export-only folders should not appear when include_scan_exports=False."""
|
||||||
|
with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as f:
|
||||||
|
path = f.name
|
||||||
|
try:
|
||||||
|
db = ProcessedDB(path)
|
||||||
|
# Manual export
|
||||||
|
db.add("a.mp4", 10.0, "/out/mp4_Intense/g1/clip.mp4", profile="test")
|
||||||
|
# Scan export to different folder
|
||||||
|
db.add("a.mp4", 20.0, "/out/mp4_ScanOnly/g1/clip.mp4", profile="test",
|
||||||
|
scan_export=True)
|
||||||
|
folders = db.get_export_folders("test")
|
||||||
|
assert "mp4_Intense" in folders
|
||||||
|
assert "mp4_ScanOnly" not in folders, "scan-only folder should be excluded"
|
||||||
|
# With include_scan_exports=True, both should appear
|
||||||
|
folders_all = db.get_export_folders("test", include_scan_exports=True)
|
||||||
|
assert "mp4_ScanOnly" in folders_all
|
||||||
|
finally:
|
||||||
|
os.unlink(path)
|
||||||
Reference in New Issue
Block a user