added additonal logging around file loading
Some checks failed
Python CI / test (push) Successful in 4m36s
Lint / lint (push) Successful in 2m11s
Tests / test (3.10) (push) Failing after 3m22s
Tests / test (3.11) (push) Failing after 1m37s
Tests / test (3.9) (push) Failing after 2m20s

This commit is contained in:
Duncan Tourolle 2025-11-27 19:55:26 +01:00
parent fc672bcdff
commit e8d9eaca51
2 changed files with 42 additions and 12 deletions

View File

@ -5,11 +5,14 @@ Data model classes for pyPhotoAlbum
from abc import ABC, abstractmethod
from typing import Tuple, Optional, Dict, Any, List
import json
import logging
import os
import uuid
from datetime import datetime, timezone
from PIL import Image
logger = logging.getLogger(__name__)
# Global configuration for asset path resolution
_asset_search_paths: List[str] = []
_primary_project_folder: Optional[str] = None
@ -349,9 +352,9 @@ class ImageData(BaseLayoutElement):
Args:
pil_image: Loaded PIL Image (already RGBA, already resized)
"""
from PIL import Image
try:
logger.debug(f"ImageData: Async load completed for {self.image_path}, size: {pil_image.size}")
# Apply PIL-level rotation if needed
if hasattr(self, 'pil_rotation_90') and self.pil_rotation_90 > 0:
# Rotate counter-clockwise by 90° * pil_rotation_90
@ -363,7 +366,7 @@ class ImageData(BaseLayoutElement):
pil_image = pil_image.transpose(Image.ROTATE_180)
elif angle == 270:
pil_image = pil_image.transpose(Image.ROTATE_90) # CCW 270 = rotate left
print(f"ImageData: Applied PIL rotation {angle}° to {self.image_path}")
logger.debug(f"ImageData: Applied PIL rotation {angle}° to {self.image_path}")
# Store the image for texture creation during next render()
# This avoids GL context issues when callback runs on wrong thread/timing
@ -375,10 +378,10 @@ class ImageData(BaseLayoutElement):
# Update metadata for future renders - always update to reflect rotated dimensions
self.image_dimensions = (pil_image.width, pil_image.height)
# print(f"ImageData: Image ready for texture creation: {self.image_path}")
logger.debug(f"ImageData: Queued for texture creation: {self.image_path}")
except Exception as e:
print(f"ImageData: Error processing async loaded image: {e}")
logger.error(f"ImageData: Error processing async loaded image {self.image_path}: {e}")
self._pending_pil_image = None
self._async_loading = False
@ -392,9 +395,19 @@ class ImageData(BaseLayoutElement):
from OpenGL.GL import (glGenTextures, glBindTexture, glTexImage2D, GL_TEXTURE_2D,
glTexParameteri, GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER,
GL_LINEAR, GL_RGBA, GL_UNSIGNED_BYTE, glDeleteTextures)
GL_LINEAR, GL_RGBA, GL_UNSIGNED_BYTE, glDeleteTextures,
glGetString, GL_VERSION)
try:
# Verify GL context is actually current before creating textures
# glGetString returns None if no context is active
gl_version = glGetString(GL_VERSION)
if gl_version is None:
# No GL context - keep pending image and try again next render
logger.debug(f"ImageData: No GL context for texture creation, deferring: {self.image_path}")
return False
logger.debug(f"ImageData: Creating texture for {self.image_path} (GL version: {gl_version})")
pil_image = self._pending_pil_image
# Delete old texture if it exists
@ -418,11 +431,27 @@ class ImageData(BaseLayoutElement):
# Clear pending image to free memory
self._pending_pil_image = None
# print(f"ImageData: Created texture for {self.image_path}")
# Clear the warning flag if we successfully created the texture
if hasattr(self, '_gl_context_warned'):
delattr(self, '_gl_context_warned')
logger.info(f"ImageData: Successfully created texture for {self.image_path}")
return True
except Exception as e:
print(f"ImageData: Error creating texture: {e}")
error_str = str(e)
# Check if this is a GL context error (err 1282 = GL_INVALID_OPERATION)
# These are typically caused by no GL context being current
if 'GLError' in error_str and '1282' in error_str:
# GL context not ready - keep pending image and try again next render
# Don't spam the console with repeated messages
if not hasattr(self, '_gl_context_warned'):
logger.warning(f"ImageData: GL context error (1282) for {self.image_path}, will retry on next render")
self._gl_context_warned = True
return False
else:
# Other error - give up on this image
logger.error(f"ImageData: Error creating texture for {self.image_path}: {e}")
self._texture_id = None
self._pending_pil_image = None
return False
@ -434,7 +463,7 @@ class ImageData(BaseLayoutElement):
Args:
error_msg: Error message
"""
print(f"ImageData: Async load failed for {self.image_path}: {error_msg}")
logger.error(f"ImageData: Async load failed for {self.image_path}: {error_msg}")
self._async_loading = False
self._async_load_requested = False

View File

@ -28,6 +28,7 @@ class TestElementWindow(ElementOperationsMixin, QMainWindow):
self.project = Mock()
self.project.history = CommandHistory()
self.project.asset_manager = Mock()
self.project.folder_path = "/tmp/test_project"
# Track method calls
self._update_view_called = False