From 2e1a8d2500a564b1b11ba469e1c2991d924a7e35 Mon Sep 17 00:00:00 2001 From: Rhet Turnbull Date: Tue, 31 Dec 2019 16:24:08 -0800 Subject: [PATCH] Added burst and burst_photos for Photos 5 --- osxphotos/_version.py | 2 +- osxphotos/photoinfo.py | 22 ++++++++++++++++ osxphotos/photosdb.py | 59 +++++++++++++++++++++++++++++++++++------- 3 files changed, 72 insertions(+), 11 deletions(-) diff --git a/osxphotos/_version.py b/osxphotos/_version.py index 61a8b134..4f304944 100644 --- a/osxphotos/_version.py +++ b/osxphotos/_version.py @@ -1,3 +1,3 @@ """ version info """ -__version__ = "0.19.03" +__version__ = "0.19.04" diff --git a/osxphotos/photoinfo.py b/osxphotos/photoinfo.py index b2f83d8b..77c1505d 100644 --- a/osxphotos/photoinfo.py +++ b/osxphotos/photoinfo.py @@ -308,6 +308,28 @@ class PhotoInfo: """ return True if self._info["type"] == _PHOTO_TYPE else False + @property + def burst(self): + """ Returns True if photo is part of a Burst photo set, otherwise False """ + # TODO: update for Photos 4 + return self._info["burst"] + + @property + def burst_photos(self): + """ If photo is a burst photo, returns list of PhotoInfo objects + that are part of the same burst photo set; otherwise returns empty list. + self is not included in the returned list """ + if self._info["burst"]: + burst_uuid = self._info["avalancheUUID"] + burst_photos = [ + PhotoInfo(db=self._db, uuid=u, info=self._db._dbphotos[u]) + for u in self._db._dbphotos_burst[burst_uuid] + if u != self._uuid + ] + return burst_photos + else: + return [] + def export( self, dest, diff --git a/osxphotos/photosdb.py b/osxphotos/photosdb.py index 89b15753..76f14d14 100644 --- a/osxphotos/photosdb.py +++ b/osxphotos/photosdb.py @@ -63,6 +63,8 @@ class PhotosDB: self._dbfile_actual = None # Dict with information about all photos by uuid self._dbphotos = {} + # Dict with information about all burst photos by burst uuid + self._dbphotos_burst = {} # Dict with information about all persons/photos by uuid self._dbfaces_uuid = {} # Dict with information about all persons/photos by person @@ -516,6 +518,11 @@ class PhotosDB: if _debug(): logging.debug(f"uuid = '{uuid}, master = '{row[2]}") self._dbphotos[uuid] = {} + + # temp fix for burst until burst photos implemented for photos 4 + # TODO: fixme + self._dbphotos[uuid]["burst"] = self._dbphotos[uuid]["burst_key"] = None + self._dbphotos[uuid]["_uuid"] = uuid # stored here for easier debugging self._dbphotos[uuid]["modelID"] = row[1] self._dbphotos[uuid]["masterUuid"] = row[2] @@ -864,13 +871,9 @@ class PhotosDB: info["masterFingerprint"] = row[1] info["name"] = row[2] try: - info["lastmodifieddate"] = datetime.fromtimestamp( - row[4] + td - ) + info["lastmodifieddate"] = datetime.fromtimestamp(row[4] + td) except: - info["lastmodifieddate"] = datetime.fromtimestamp( - row[5] + td - ) + info["lastmodifieddate"] = datetime.fromtimestamp(row[5] + td) info["imageDate"] = datetime.fromtimestamp(row[5] + td) info["imageTimeZoneOffsetSeconds"] = row[6] @@ -914,13 +917,41 @@ class PhotosDB: info["type"] = None info["UTI"] = row[18] + info["avalancheUUID"] = row[19] + info["avalanchePickType"] = row[20] + + # handle burst photos + # if burst photo, determine whether or not it's a selected burst photo + if row[19] is not None: + # it's a burst photo + info["burst"] = True + burst_uuid = row[19] + if burst_uuid not in self._dbphotos_burst: + self._dbphotos_burst[burst_uuid] = set() + self._dbphotos_burst[burst_uuid].add(uuid) + if row[20] != 2 and row[20] != 4: + info["burst_key"] = True # it's a key photo (selected from the burst) + else: + info["burst_key"] = False # it's a burst photo but not one that's selected + else: + # not a burst photo + info["burst"] = False + info["burst_key"] = None - # TODO: fixme temp fix to filter unselected burst photos - if row[19] is not None and ((row[20] == 2) or (row[20] == 4)): - # burst photo - continue self._dbphotos[uuid] = info + # # if row[19] is not None and ((row[20] == 2) or (row[20] == 4)): + # # burst photo + # if row[19] is not None: + # # burst photo, add to _dbphotos_burst + # info["burst"] = True + # burst_uuid = row[19] + # if burst_uuid not in self._dbphotos_burst: + # self._dbphotos_burst[burst_uuid] = {} + # self._dbphotos_burst[burst_uuid][uuid] = info + # else: + # info["burst"] = False + # Get extended description c.execute( "SELECT ZGENERICASSET.ZUUID, " @@ -1082,6 +1113,9 @@ class PhotosDB: logging.debug("Photos:") logging.debug(pformat(self._dbphotos)) + logging.debug("Burst Photos:") + logging.debug(pformat(self._dbphotos_burst)) + # TODO: fix default values to None instead of [] def photos( self, @@ -1151,6 +1185,11 @@ class PhotosDB: # get the intersection of each argument/search criteria logging.debug(f"Got photo_sets: {photos_sets}") for p in set.intersection(*photos_sets): + # filter for non-selected burst photos + if self._dbphotos[p]["burst"] and not self._dbphotos[p]["burst_key"]: + # not a key/selected burst photo, don't include in returned results + continue + # filter for images and/or movies if (images and self._dbphotos[p]["type"] == _PHOTO_TYPE) or ( movies and self._dbphotos[p]["type"] == _MOVIE_TYPE