"""Pytest configuration and fixtures for AI Creative Studio & Moldovan AI Media Studio. """ import glob import json import os import sys import tempfile from pathlib import Path import pytest PROJECT_ROOT = Path(__file__).resolve().parent.parent MOLDOVAN_DIR = PROJECT_ROOT / "moldovan-qwen" # Ensure root and subproject are on sys.path if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) if str(MOLDOVAN_DIR) not in sys.path: sys.path.insert(0, str(MOLDOVAN_DIR)) # Set test environment flags os.environ["HF_SKIP_PRELOAD"] = "1" os.environ["TESTING"] = "1" # Isolate ALL generated-media writes away from the real repo data/ tree. # MOLDOVAN_DATA_ROOT is read by media_creator.py, studio_server.py, and # daily_album_cron.py at import time; a per-process scratch root keeps the # repo clean while still exercising real file I/O. _REPO_DATA = MOLDOVAN_DIR / "data" _DATA_ROOT = os.environ.get("MOLDOVAN_DATA_ROOT") or os.path.join( tempfile.gettempdir(), "moldovan_qwen_test_data" ) os.environ["MOLDOVAN_DATA_ROOT"] = _DATA_ROOT def _seed_scratch_data_root() -> None: """Copy read-only seed sources from the repo data/ into the scratch root once. Modules write generated artifacts under MOLDOVAN_DATA_ROOT, but they also READ seed inputs (lexicon, regionalisms, corpus, phonetic dictionary, master dictionary). Copy them so tests see real data while the repo data/ tree stays untouched. """ import shutil os.makedirs(_DATA_ROOT, exist_ok=True) seeds = [ "moldovan_lexicon.json", "regionalisme_moldovenesc.jsonl", "moldovan_master_dictionary.json", "phonetic_dictionary.json", ] for name in seeds: src = _REPO_DATA / name dst = os.path.join(_DATA_ROOT, name) if src.exists() and not os.path.exists(dst): shutil.copy2(src, dst) corpus_src = _REPO_DATA / "youtube_corpus" corpus_dst = os.path.join(_DATA_ROOT, "youtube_corpus") if corpus_src.exists() and not os.path.exists(corpus_dst): shutil.copytree(corpus_src, corpus_dst) # Read-only storyboards: DOM closure tests drive the timeline UI from these # (44 sampled chips + selectable scenes). Server never writes here in tests. scripts_src = _REPO_DATA / "generated_video_scripts" scripts_dst = os.path.join(_DATA_ROOT, "generated_video_scripts") if scripts_src.exists() and not os.path.exists(scripts_dst): shutil.copytree(scripts_src, scripts_dst) # Sanitize: drop absolute image references so scratch data is # self-contained (no console 404s for images not copied to scratch). for sp in glob.glob(os.path.join(scripts_dst, "*.json")): try: with open(sp, "r", encoding="utf-8") as f: board = json.load(f) for scene in board.get("scenes", []): scene.pop("image_url", None) scene.pop("image_path", None) with open(sp, "w", encoding="utf-8") as f: json.dump(board, f, ensure_ascii=False) except Exception: pass _seed_scratch_data_root() os.makedirs(os.path.join(_DATA_ROOT, "generated_music"), exist_ok=True) @pytest.fixture(autouse=True) def setup_test_env(monkeypatch): """Automatically ensure test flags and paths are set for all tests.""" monkeypatch.setenv("HF_SKIP_PRELOAD", "1") monkeypatch.setenv("TESTING", "1") monkeypatch.setenv("MOLDOVAN_DATA_ROOT", _DATA_ROOT)