From 47e24545847bb8270319d3c279f2d79396f2f2df Mon Sep 17 00:00:00 2001 From: Rhet Turnbull Date: Tue, 13 Dec 2022 22:55:17 -0800 Subject: [PATCH] Bug edited path bad mojave 859 (#870) * Partial fix for #859, missing path edited on Mojave * Fixed annotation issue * Fix for HEIC edited images on Mojave, #859 * Additional fix for live photo edited paths, #859 --- osxphotos/photoinfo.py | 23 +++++++------ osxphotos/photosdb/photosdb.py | 61 ++++++++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 23 deletions(-) diff --git a/osxphotos/photoinfo.py b/osxphotos/photoinfo.py index 59ca703f..cb1bd1ca 100644 --- a/osxphotos/photoinfo.py +++ b/osxphotos/photoinfo.py @@ -281,7 +281,7 @@ class PhotoInfo: def _get_predicted_path_edited_4(self) -> str | None: """return predicted path_edited for Photos <= 4""" - edit_id = self._info["edit_resource_id"] + edit_id = self._info["edit_resource_id_photo"] folder_id, file_id, nn_id = _get_resource_loc(edit_id) # figure out what kind it is and build filename library = self._db._library_path @@ -357,21 +357,24 @@ class PhotoInfo: def _get_predicted_path_edited_live_photo_4(self) -> str | None: """return predicted path_edited for Photos <= 4""" - edit_id = self._info["edit_resource_id"] - folder_id, file_id, nn_id = _get_resource_loc(edit_id) - # figure out what kind it is and build filename - library = self._db._library_path - filename = f"videocomplementoutput_{file_id}.mov" - return os.path.join( - library, "resources", "media", "version", folder_id, nn_id, filename - ) + # need the resource id for the video, not the photo (edit_resource_id is for photo) + if edit_id := self._info["edit_resource_id_video"]: + folder_id, file_id, nn_id = _get_resource_loc(edit_id) + # figure out what kind it is and build filename + library = self._db._library_path + filename = f"videocomplementoutput_{file_id}.mov" + return os.path.join( + library, "resources", "media", "version", folder_id, nn_id, filename + ) + else: + return None def _path_edited_4_live_photo(self): """return path_edited_live_photo for Photos <= 4""" if self._db._db_version > _PHOTOS_4_VERSION: raise RuntimeError("Wrong database format!") photopath = self._get_predicted_path_edited_live_photo_4() - if not os.path.isfile(photopath): + if photopath is not None and not os.path.isfile(photopath): # the heuristic failed, so try to find the file rootdir = pathlib.Path(photopath).parent.parent filename = pathlib.Path(photopath).name diff --git a/osxphotos/photosdb/photosdb.py b/osxphotos/photosdb/photosdb.py index ff297bf0..9b5a6590 100644 --- a/osxphotos/photosdb/photosdb.py +++ b/osxphotos/photosdb/photosdb.py @@ -1322,16 +1322,30 @@ class PhotosDB: and row[1] != "UNADJUSTED" and row[6] == 2 ): - if "edit_resource_id" in self._dbphotos[uuid]: - if is_debug(): - logging.debug( - f"WARNING: found more than one edit_resource_id for " - f"UUID {row[0]},adjustmentUUID {row[1]}, modelID {row[2]}" - ) - # Sometimes the library has multiple edits for a photo - # Not sure why, but we'll just use the most recent one - self._dbphotos[uuid]["edit_resource_id"] = row[2] - self._dbphotos[uuid]["UTI_edited"] = row[4] + resource_type = row[7] + # UTI_edited will be set to the appropriate UTI for the edited resource below + # a live photo that's edited will have both a photo and video resource but the photo + # UTI will be used for the edited live photo, see #859 + if resource_type == 4: + # photo + if "edit_resource_id_photo" in self._dbphotos[uuid]: + if is_debug(): + logging.debug( + f"WARNING: found more than one edit_resource_id_photo for " + f"UUID {row[0]},adjustmentUUID {row[1]}, modelID {row[2]}" + ) + self._dbphotos[uuid]["edit_resource_id_photo"] = row[2] + self._dbphotos[uuid]["UTI_edited_photo"] = row[4] + elif resource_type == 8: + # video + if "edit_resource_id_video" in self._dbphotos[uuid]: + if is_debug(): + logging.debug( + f"WARNING: found more than one edit_resource_id_video for " + f"UUID {row[0]},adjustmentUUID {row[1]}, modelID {row[2]}" + ) + self._dbphotos[uuid]["edit_resource_id_video"] = row[2] + self._dbphotos[uuid]["UTI_edited_video"] = row[4] # get details on external edits c.execute( @@ -1384,9 +1398,27 @@ class PhotosDB: ) # init any uuids that had no edits or live photos + # also initialized UTI_edited and edit_resource_id for uuid in self._dbphotos: - if "edit_resource_id" not in self._dbphotos[uuid]: - self._dbphotos[uuid]["edit_resource_id"] = None + if "edit_resource_id_photo" not in self._dbphotos[uuid]: + self._dbphotos[uuid]["edit_resource_id_photo"] = None + if "edit_resource_id_video" not in self._dbphotos[uuid]: + self._dbphotos[uuid]["edit_resource_id_video"] = None + if "UTI_edited_photo" not in self._dbphotos[uuid]: + self._dbphotos[uuid]["UTI_edited_photo"] = None + if "UTI_edited_video" not in self._dbphotos[uuid]: + self._dbphotos[uuid]["UTI_edited_video"] = None + # UTI_edited will be set to the appropriate UTI for the edited resource below + # a live photo that's edited will have both a photo and video resource but the photo + # UTI will be used for the edited live photo + self._dbphotos[uuid]["UTI_edited"] = ( + self._dbphotos[uuid]["UTI_edited_photo"] + or self._dbphotos[uuid]["UTI_edited_video"] + ) + self._dbphotos[uuid]["edit_resource_id"] = ( + self._dbphotos[uuid]["edit_resource_id_photo"] + or self._dbphotos[uuid]["edit_resource_id_video"] + ) if "live_model_id" not in self._dbphotos[uuid]: self._dbphotos[uuid]["live_model_id"] = None self._dbphotos[uuid]["modeResourceIsOnDisk"] = None @@ -2171,7 +2203,10 @@ class PhotosDB: info["raw_info"] = None # Photos 4 # Photos 4 only - info["edit_resource_id"] = None + info["edit_resource_id_photo"] = None + info["edit_resource_id_video"] = None + info["UTI_edited_photo"] = None + info["UTI_edited_video"] = None self._dbphotos[uuid] = info