pyPhotoAlbum/tests/test_heal_function.py
Duncan Tourolle 0d698a83b4
Some checks failed
Python CI / test (push) Successful in 55s
Lint / lint (push) Successful in 1m31s
Tests / test (3.10) (push) Failing after 44s
Tests / test (3.11) (push) Failing after 42s
Tests / test (3.9) (push) Failing after 42s
large change to allow project merging
2025-11-23 00:33:42 +01:00

156 lines
5.8 KiB
Python
Executable File

#!/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)