Fixed handling of burst image selected/key/default, closes #401 (again)

This commit is contained in:
Rhet Turnbull
2021-04-24 19:43:35 -07:00
parent 48c229b52c
commit 3711b3f7f1
27 changed files with 861 additions and 137 deletions

View File

@@ -209,4 +209,11 @@ EXTENDED_ATTRIBUTE_NAMES = [
EXTENDED_ATTRIBUTE_NAMES_QUOTED = [f"'{x}'" for x in EXTENDED_ATTRIBUTE_NAMES]
# name of export DB
OSXPHOTOS_EXPORT_DB = ".osxphotos_export.db"
OSXPHOTOS_EXPORT_DB = ".osxphotos_export.db"
# bit flags for burst images ("burstPickType")
BURST_NOT_SELECTED = 0b10 # 2: burst image is not selected
BURST_DEFAULT_PICK = 0b100 # 4: burst image is the one Photos picked to be key image before any selections made
BURST_SELECTED = 0b1000 # 8: burst image is selected
BURST_KEY = 0b10000 # 16: burst image is the key photo (top of burst stack)
BURST_UNKNOWN = 0b100000 # 32: this is almost always set with BURST_DEFAULT_PICK and never if BURST_DEFAULT_PICK is not set. I think this has something to do with what algorithm Photos used to pick the default image

View File

@@ -1,3 +1,3 @@
""" version info """
__version__ = "0.42.10"
__version__ = "0.42.11"

View File

@@ -26,6 +26,10 @@ from .._constants import (
_PHOTOS_5_SHARED_ALBUM_KIND,
_PHOTOS_5_SHARED_PHOTO_PATH,
_PHOTOS_5_VERSION,
BURST_DEFAULT_PICK,
BURST_KEY,
BURST_NOT_SELECTED,
BURST_SELECTED,
)
from ..adjustmentsinfo import AdjustmentsInfo
from ..albuminfo import AlbumInfo, ImportInfo
@@ -455,16 +459,14 @@ class PhotoInfo:
@property
def burst_albums(self):
"""If photo is non-selected burst photo, list of albums any other images in the same burst set are contained in, otherwise returns self.albums"""
if self.burst_selected or not self.burst:
return self.albums
"""If photo is burst photo, list of albums it is contained in as well as any albums the key photo is contained in, otherwise returns self.albums """
try:
return self._burst_albums
except AttributeError:
burst_albums = []
burst_albums = list(self.albums)
for photo in self.burst_photos:
burst_albums.extend(photo.albums)
if photo.burst_key:
burst_albums.extend(photo.albums)
self._burst_albums = list(set(burst_albums))
return self._burst_albums
@@ -482,16 +484,14 @@ class PhotoInfo:
@property
def burst_album_info(self):
""" If photo is a non-selected burst photo, returns list of AlbumInfo objects representing albums any other photos in the same burst set are contained in, otherwise returns self.album_info """
if self.burst_selected or not self.burst:
return self.album_info
""" If photo is a burst photo, returns list of AlbumInfo objects representing albums the photo is contained in as well as albums the burst key photo is contained in, otherwise returns self.album_info. """
try:
return self._burst_album_info
except AttributeError:
burst_album_info = []
burst_album_info = list(self.album_info)
for photo in self.burst_photos:
burst_album_info.extend(photo.album_info)
if photo.burst_key:
burst_album_info.extend(photo.album_info)
self._burst_album_info = list(set(burst_album_info))
return self._burst_album_info
@@ -713,7 +713,17 @@ class PhotoInfo:
@property
def burst_selected(self):
""" Returns True if photo is a burst photo and has been selected from the burst set by the user, otherwise False """
return self._info["burst_key"]
return bool(self._info["burstPickType"] & BURST_SELECTED)
@property
def burst_key(self):
""" Returns True if photo is a burst photo and is the key image for the burst set (the image that Photos shows on top of the burst stack), otherwise False """
return bool(self._info["burstPickType"] & BURST_KEY)
@property
def burst_default_pick(self):
""" Returns True if photo is a burst image and is the photo that Photos selected as the default image for the burst set, otherwise False """
return bool(self._info["burstPickType"] & BURST_DEFAULT_PICK)
@property
def burst_photos(self):

View File

@@ -1227,7 +1227,7 @@ class PhotoLibrary:
Args:
burstid: str, burst UUID
all: return all burst assets; if False returns only those selected by the user
all: return all burst assets; if False returns only those selected by the user (including the "key photo" even if user hasn't manually selected it)
Returns:
list of PhotoAsset objects

View File

@@ -33,6 +33,8 @@ from .._constants import (
_PHOTOS_5_SHARED_ALBUM_KIND,
_TESTED_OS_VERSIONS,
_UNKNOWN_PERSON,
BURST_KEY,
BURST_SELECTED,
TIME_DELTA,
)
from .._version import __version__
@@ -41,6 +43,7 @@ from ..datetime_utils import datetime_has_tz, datetime_naive_to_local
from ..fileutil import FileUtil
from ..personinfo import PersonInfo
from ..photoinfo import PhotoInfo
from ..queryoptions import QueryOptions
from ..utils import (
_check_file_exists,
_db_is_locked,
@@ -51,7 +54,6 @@ from ..utils import (
noop,
normalize_unicode,
)
from ..queryoptions import QueryOptions
from .photosdb_utils import get_db_model_version, get_db_version
# TODO: Add test for imageTimeZoneOffsetSeconds = None
@@ -1067,18 +1069,9 @@ class PhotosDB:
if burst_uuid not in self._dbphotos_burst:
self._dbphotos_burst[burst_uuid] = set()
self._dbphotos_burst[burst_uuid].add(uuid)
if row[24] != 2 and row[24] != 4:
self._dbphotos[uuid][
"burst_key"
] = True # it's a key photo (selected from the burst)
else:
self._dbphotos[uuid][
"burst_key"
] = False # it's a burst photo but not one that's selected
else:
# not a burst photo
self._dbphotos[uuid]["burst"] = False
self._dbphotos[uuid]["burst_key"] = None
# RKVersion.specialType
# 1 == panorama
@@ -2010,18 +2003,9 @@ class PhotosDB:
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
# Info on sub-type (live photo, panorama, etc)
# ZGENERICASSET.ZKINDSUBTYPE
@@ -2787,7 +2771,10 @@ class PhotosDB:
# get the intersection of each argument/search criteria
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"]:
if self._dbphotos[p]["burst"] and not (
self._dbphotos[p]["burstPickType"] & BURST_SELECTED
or self._dbphotos[p]["burstPickType"] & BURST_KEY
):
# not a key/selected burst photo, don't include in returned results
continue
@@ -3234,4 +3221,3 @@ def _get_photos_by_attribute(photos, attribute, values, ignore_case):
for x in values:
photos_search.extend(p for p in photos if x in getattr(p, attribute))
return photos_search