Files
2026-09-24 22:04:04 +02:00

92 lines
3.3 KiB
Python

"""Works out what SaraSortd made on its own while running, by reading
GlobalConf.toml the same way SaraSortd.py does (see its Parse/GetConf/Init).
It never removes the user's files: the input/output/failed folders are only
removed if they're empty once SaraSortd's own files are gone.
"""
import re
from pathlib import Path
import tomlkit
from Manifests import Leftover
def _Find(Conf: dict, Key: str):
"""SaraSortd's GetConf: a top-level key, or one inside a table/array of tables."""
if Key in Conf:
return Conf[Key]
for Value in Conf.values():
if isinstance(Value, dict) and Key in Value:
return Value[Key]
if isinstance(Value, list):
for Item in Value:
if isinstance(Item, dict) and Key in Item:
return Item[Key]
return None
def _Resolve(Text: str, Conf: dict) -> str:
"""SaraSortd's %Var% substitution (single pass, like its Parse)."""
VarCall = Conf.get("Variables", {}).get("VarCall", "%%")
Pattern = f"{re.escape(VarCall[0])}(.*?){re.escape(VarCall[1])}"
def Replace(Match: re.Match) -> str:
Value = _Find(Conf, Match[1]) if Match[1] else None
return str(Value) if Value is not None else Match[0]
return re.sub(Pattern, Replace, Text)
def _DirFileName(Conf: dict, NameKey: str, DirPath: Path) -> str:
"""e.g. ".@Config" for a folder named Input -> ".InputConfig.toml"."""
Parent = Conf.get("Variables", {}).get("Parent", "@")
Name = Conf.get("Names", {}).get(NameKey, "")
return f"{Name.replace(Parent, DirPath.name)}.toml" if Name else ""
def Leftovers(Context: dict) -> list[Leftover]:
ConfPath = Path(Context["ConfigDir"]) / "GlobalConf.toml"
if not ConfPath.exists():
return []
try:
Conf = tomlkit.parse(ConfPath.read_text()).unwrap()
except tomlkit.exceptions.TOMLKitError:
return []
Paths = Conf.get("DirectoryPaths", {})
Found: list[Leftover] = []
Folders = []
for Key in ("InputDir", "OutputDir"):
Entries = Paths.get(Key, [])
for Entry in Entries if isinstance(Entries, list) else [Entries]:
Folders.append(Path(_Resolve(str(Entry), Conf)))
for Folder in Folders:
for NameKey in ("InDirConfName", "OutDirConfName", "DirConfName"):
FileName = _DirFileName(Conf, NameKey, Folder)
if FileName:
Found.append(Leftover(str(Folder / FileName), "Config", Note="this folder's SaraSortd rules"))
HistoryName = _DirFileName(Conf, "FileHistoryName", Folder)
if HistoryName:
Found.append(Leftover(str(Folder / HistoryName), "Runtime", Note="sorting history"))
Found.append(Leftover(str(Folder), "Runtime", "IfEmpty", "only if empty"))
LogDir = Paths.get("LogDir")
if LogDir:
LogDir = _Resolve(str(LogDir), Conf)
Found.append(Leftover(f"{LogDir}/*.log", "Runtime", Note="log"))
Found.append(Leftover(LogDir, "Runtime", "IfEmpty", "only if empty"))
FailedDir = Paths.get("FailedDir")
if FailedDir:
Found.append(Leftover(_Resolve(str(FailedDir), Conf), "Runtime", "IfEmpty", "only if empty, it holds files that failed to sort"))
RootDir = Paths.get("RootDir")
if RootDir and RootDir != "Unset":
Found.append(Leftover(_Resolve(str(RootDir), Conf), "Runtime", "IfEmpty", "only if empty"))
return Found