#!/usr/bin/env python3 """ Test to verify the heal function can fix old files with missing assets """ import os import sys import tempfile import shutil sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from pyPhotoAlbum.project import Project, Page from pyPhotoAlbum.models import ImageData from pyPhotoAlbum.project_serializer import save_to_zip, load_from_zip def test_heal_external_paths(): """Test healing a project with external (absolute) image paths""" print("=" * 70) print("Test: Healing External Image Paths") print("=" * 70) # Create a test image in a temp location with tempfile.TemporaryDirectory() as temp_dir: # Create a test image file test_image_source = "./projects/project_with_image/assets/test_image.jpg" external_image_path = os.path.join(temp_dir, "external_photo.jpg") shutil.copy2(test_image_source, external_image_path) print(f"\n1. Created external image at: {external_image_path}") # Create a project project = Project("Test Heal") page = Page() project.add_page(page) # Add an image element with ABSOLUTE path (simulating the bug) img = ImageData() img.image_path = external_image_path # BUG: Absolute path! img.position = (10, 10) img.size = (50, 50) page.layout.add_element(img) print(f"2. Created project with absolute path: {img.image_path}") # Save to zip with tempfile.NamedTemporaryFile(suffix='.ppz', delete=False) as tmp: zip_path = tmp.name save_to_zip(project, zip_path) print(f"3. Saved to: {zip_path}") # Check what was saved import zipfile with zipfile.ZipFile(zip_path, 'r') as zf: files = zf.namelist() asset_files = [f for f in files if f.startswith('assets/')] print(f"\n4. Assets in zip: {len(asset_files)}") if len(asset_files) == 0: print(" ❌ No assets saved (expected - this is the bug!)") else: print(f" ✅ Assets: {asset_files}") # Load the project try: loaded_project = load_from_zip(zip_path) print(f"\n5. Loaded project from zip") except Exception as error: print(f" ❌ Failed to load: {error}") return False # Check for missing assets from pyPhotoAlbum.models import ImageData as ImageDataCheck missing_count = 0 for page in loaded_project.pages: for element in page.layout.elements: if isinstance(element, ImageDataCheck) and element.image_path: if os.path.isabs(element.image_path): full_path = element.image_path else: full_path = os.path.join(loaded_project.folder_path, element.image_path) if not os.path.exists(full_path): missing_count += 1 print(f" ❌ Missing: {element.image_path}") print(f"\n6. Missing assets detected: {missing_count}") if missing_count == 0: print(" ⚠️ No missing assets - test may not be accurate") return False # Now test the healing logic print(f"\n7. Testing heal function...") # Simulate what the heal dialog does from pyPhotoAlbum.models import set_asset_resolution_context search_paths = [temp_dir] # The directory where our external image is set_asset_resolution_context(loaded_project.folder_path, search_paths) healed_count = 0 for page in loaded_project.pages: for element in page.layout.elements: if isinstance(element, ImageDataCheck) and element.image_path: # Check if missing if os.path.isabs(element.image_path): full_path = element.image_path else: full_path = os.path.join(loaded_project.folder_path, element.image_path) if not os.path.exists(full_path): # Try to find and import filename = os.path.basename(element.image_path) for search_path in search_paths: candidate = os.path.join(search_path, filename) if os.path.exists(candidate): # Import it! new_asset_path = loaded_project.asset_manager.import_asset(candidate) element.image_path = new_asset_path healed_count += 1 print(f" ✅ Healed: {filename} → {new_asset_path}") break print(f"\n8. Healed {healed_count} asset(s)") # Save the healed project healed_zip_path = zip_path.replace('.ppz', '_healed.ppz') save_to_zip(loaded_project, healed_zip_path) print(f"9. Saved healed project to: {healed_zip_path}") # Verify the healed version has assets with zipfile.ZipFile(healed_zip_path, 'r') as zf: files = zf.namelist() asset_files = [f for f in files if f.startswith('assets/')] print(f"\n10. Assets in healed zip: {len(asset_files)}") for asset in asset_files: print(f" - {asset}") # Cleanup loaded_project.cleanup() os.unlink(zip_path) os.unlink(healed_zip_path) if healed_count > 0 and len(asset_files) > 0: print("\n✅ HEAL FUNCTION WORKS - Old files can be fixed!") return True else: print("\n❌ Healing did not work as expected") return False if __name__ == "__main__": success = test_heal_external_paths() sys.exit(0 if success else 1)