Add ČSFD Anubis bypass, drop legacy preset tags, rename Země → Země původu
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
"""One-off migration: rename a tag category inside a pool's metadata index.
|
||||
|
||||
Tags are stored in ``<pool>/.Curator.!index`` as ``"Category/Name"`` strings.
|
||||
This rewrites every tag whose category matches ``--old`` to use ``--new``,
|
||||
leaving the tag name untouched. A timestamped backup of the index is written
|
||||
before saving.
|
||||
|
||||
Usage:
|
||||
poetry run python scripts/migrate_tag_category.py <pool_dir> \
|
||||
--old "Země" --new "Země původu"
|
||||
|
||||
If ``<pool_dir>`` is omitted, the pool from the global config is used.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import json
|
||||
import shutil
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
from loguru import logger
|
||||
|
||||
# Allow running as a plain script (``python scripts/...``) by exposing the repo root.
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||
|
||||
from src.core.config import load_global_config # noqa: E402
|
||||
from src.core.pool_index import INDEX_FILENAME # noqa: E402
|
||||
|
||||
|
||||
def _rename_in_tags(tags: list[str], old: str, new: str) -> tuple[list[str], int]:
|
||||
"""Return (rewritten tags, number of tags changed) for one record."""
|
||||
prefix = f"{old}/"
|
||||
changed = 0
|
||||
result: list[str] = []
|
||||
for tag in tags:
|
||||
if isinstance(tag, str) and tag.startswith(prefix):
|
||||
result.append(f"{new}/{tag[len(prefix):]}")
|
||||
changed += 1
|
||||
else:
|
||||
result.append(tag)
|
||||
return result, changed
|
||||
|
||||
|
||||
def migrate(index_path: Path, old: str, new: str) -> int:
|
||||
"""Rewrite the category in place and return the number of tags changed."""
|
||||
with open(index_path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
movies: dict[str, dict] = data.get("movies", {})
|
||||
total_changed = 0
|
||||
affected_records = 0
|
||||
for key, record in movies.items():
|
||||
tags = record.get("tags", [])
|
||||
new_tags, changed = _rename_in_tags(tags, old, new)
|
||||
if changed:
|
||||
record["tags"] = new_tags
|
||||
total_changed += changed
|
||||
affected_records += 1
|
||||
logger.debug(f"{key}: {changed} tag(s) renamed")
|
||||
|
||||
if total_changed == 0:
|
||||
logger.info(f"No '{old}/…' tags found — nothing to migrate")
|
||||
return 0
|
||||
|
||||
backup = index_path.with_suffix(
|
||||
index_path.suffix + f".bak-{datetime.now():%Y%m%d-%H%M%S}"
|
||||
)
|
||||
shutil.copy2(index_path, backup)
|
||||
logger.info(f"Backup written: {backup}")
|
||||
|
||||
with open(index_path, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, indent=2, ensure_ascii=False)
|
||||
|
||||
logger.info(
|
||||
f"Migrated '{old}' → '{new}': {total_changed} tag(s) "
|
||||
f"across {affected_records} record(s)"
|
||||
)
|
||||
return total_changed
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument(
|
||||
"pool_dir",
|
||||
nargs="?",
|
||||
help="Pool root (default: pool_dir from the global config)",
|
||||
)
|
||||
parser.add_argument("--old", default="Země", help="Category to rename from")
|
||||
parser.add_argument("--new", default="Země původu", help="Category to rename to")
|
||||
args = parser.parse_args()
|
||||
|
||||
pool_dir = args.pool_dir or load_global_config().get("pool_dir")
|
||||
if not pool_dir:
|
||||
parser.error("No pool_dir given and none configured in the global config")
|
||||
|
||||
index_path = Path(pool_dir) / INDEX_FILENAME
|
||||
if not index_path.exists():
|
||||
parser.error(f"No index found at {index_path}")
|
||||
|
||||
migrate(index_path, args.old, args.new)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user