"""Characterization parity: the extracted safety logic matches the donor on the same fixture files (real exiftool-written keywords).""" import shutil import subprocess import sys from pathlib import Path import numpy as np import pytest from PIL import Image from photo_pipeline.integrations import exiftool from photo_pipeline.services import safety # The donor is frozen in the read-only archive (US07-01); parity still compares # against it, so this suite is the second and last place that may import it. ARCHIVED_SOURCES = Path(__file__).resolve().parents[2] / "legacy_cli_archive" / "src" EXIFTOOL = shutil.which("exiftool") pytestmark = pytest.mark.skipif(EXIFTOOL is None, reason="exiftool not installed") def _jpeg(path, seed=1): path.parent.mkdir(parents=True, exist_ok=True) arr = np.random.default_rng(seed).integers(0, 256, (32, 32, 3), dtype=np.uint8) Image.fromarray(arr).save(path, quality=90) return str(path) def _tag(path, keyword): subprocess.run( ["exiftool", "-m", "-overwrite_original", f"-Keywords={keyword}", f"-Subject={keyword}", path], check=True, capture_output=True, ) def test_extracted_marks_and_partition_match_donor(tmp_path): sys.path.insert(0, str(ARCHIVED_SOURCES)) # the donor lives in the archive now donor_exif = pytest.importorskip("nsfwtag.exif") nsfw = _jpeg(tmp_path / "nsfw.jpg", 1) sfw = _jpeg(tmp_path / "sfw.jpg", 2) plain = _jpeg(tmp_path / "plain.jpg", 3) _tag(nsfw, "nsfw") _tag(sfw, "sfw") paths = [nsfw, sfw, plain] # Donor behavior. donor_marks = donor_exif.read_marks(paths) donor_nsfw = donor_exif.read_tagged(paths, "nsfw") # Extracted behavior on the same files. keyword_sets = exiftool.read_keyword_sets(paths) extracted_marks = safety.marks_from_keywords(keyword_sets) _, skipped = safety.partition_nsfw(keyword_sets) assert extracted_marks == donor_marks assert set(skipped) == donor_nsfw assert extracted_marks["nsfw"] == {nsfw} assert extracted_marks["sfw"] == {sfw}