From 10284d65897600a18d04c4dedd33230f0b3973ba Mon Sep 17 00:00:00 2001 From: Rhet Turnbull Date: Thu, 26 Dec 2019 00:18:29 -0800 Subject: [PATCH] Initial shared photos code for Photos 5 --- osxphotos/_constants.py | 3 ++ osxphotos/photoinfo.py | 67 ++++++++++++++++++++++++++--------------- osxphotos/photosdb.py | 2 ++ 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/osxphotos/_constants.py b/osxphotos/_constants.py index d07270df..a93c8e3f 100644 --- a/osxphotos/_constants.py +++ b/osxphotos/_constants.py @@ -21,3 +21,6 @@ _TESTED_OS_VERSIONS = ["12", "13", "14", "15"] _UNKNOWN_PERSON = "_UNKNOWN_" _EXIF_TOOL_URL = "https://exiftool.org/" + +# Where are shared iCloud photos located? +_PHOTOS_5_SHARED_PHOTO_PATH = "resources/cloudsharing/data" diff --git a/osxphotos/photoinfo.py b/osxphotos/photoinfo.py index e7095803..7164c1e8 100644 --- a/osxphotos/photoinfo.py +++ b/osxphotos/photoinfo.py @@ -16,7 +16,7 @@ from pprint import pformat import yaml -from ._constants import _PHOTOS_5_VERSION +from ._constants import _PHOTOS_5_VERSION, _PHOTOS_5_SHARED_PHOTO_PATH from .utils import _get_resource_loc, dd_to_dms_str # TODO: check pylint output @@ -62,7 +62,10 @@ class PhotoInfo: @property def path(self): """ absolute path on disk of the original picture """ - photopath = "" + + photopath = None + if self._info["isMissing"] == 1: + return photopath # path would be meaningless until downloaded if self._db._db_version < _PHOTOS_5_VERSION: vol = self._info["volume"] @@ -72,33 +75,38 @@ class PhotoInfo: photopath = os.path.join( self._db._masters_path, self._info["imagePath"] ) + return photopath + # TODO: Is there a way to use applescript or PhotoKit to force the download in this - if self._info["isMissing"] == 1: - photopath = None # path would be meaningless until downloaded - # TODO: Is there a way to use applescript or PhotoKit to force the download in this - else: - if self._info["masterFingerprint"]: - # if masterFingerprint is not null, path appears to be valid - if self._info["directory"].startswith("/"): - photopath = os.path.join( - self._info["directory"], self._info["filename"] - ) - else: - photopath = os.path.join( - self._db._masters_path, - self._info["directory"], - self._info["filename"], - ) + if self._info["masterFingerprint"]: + # if masterFingerprint is not null, path appears to be valid + if self._info["directory"].startswith("/"): + photopath = os.path.join( + self._info["directory"], self._info["filename"] + ) else: - photopath = None - logging.debug(f"WARNING: masterFingerprint null {pformat(self._info)}") + photopath = os.path.join( + self._db._masters_path, + self._info["directory"], + self._info["filename"], + ) + return photopath - # TODO: fix the logic for isMissing - if self._info["isMissing"] == 1: - photopath = None # path would be meaningless until downloaded - - logging.debug(photopath) + if self._info["shared"]: + # shared photo + photopath = os.path.join( + self._db._library_path, + _PHOTOS_5_SHARED_PHOTO_PATH, + self._info["directory"], + self._info["filename"], + ) + return photopath + # if all else fails, photopath = None + photopath = None + logging.debug( + f"WARNING: photopath None, masterFingerprint null, not shared {pformat(self._info)}" + ) return photopath @property @@ -250,6 +258,15 @@ class PhotoInfo: """ returns (latitude, longitude) as float in degrees or None """ return (self._latitude, self._longitude) + @property + def shared(self): + """ returns True if photos is in a shared iCloud album otherwise false + Only valid on Photos 5; returns None on older versions """ + if self._db._db_version >= _PHOTOS_5_VERSION: + return self._info["shared"] + else: + return None + def export( self, dest, diff --git a/osxphotos/photosdb.py b/osxphotos/photosdb.py index dfe13904..5f8e332d 100644 --- a/osxphotos/photosdb.py +++ b/osxphotos/photosdb.py @@ -900,7 +900,9 @@ class PhotosDB: self._dbphotos[uuid]["longitude"] = row[14] self._dbphotos[uuid]["hasAdjustments"] = row[15] + self._dbphotos[uuid]["cloudOwnerHashedPersonID"] = row[16] + self._dbphotos[uuid]["shared"] = True if row[16] is not None else False # these will get filled in later # init to avoid key errors