Added isreference property and --is-reference, #321
This commit is contained in:
@@ -674,6 +674,11 @@ def query_options(f):
|
||||
o("--no-comment", is_flag=True, help="Search for photos with no comments."),
|
||||
o("--has-likes", is_flag=True, help="Search for photos that have likes."),
|
||||
o("--no-likes", is_flag=True, help="Search for photos with no likes."),
|
||||
o(
|
||||
"--is-reference",
|
||||
is_flag=True,
|
||||
help="Search for photos that were imported as referenced files (not copied into Photos library).",
|
||||
),
|
||||
]
|
||||
for o in options[::-1]:
|
||||
f = o(f)
|
||||
@@ -1166,6 +1171,7 @@ def export(
|
||||
exportdb,
|
||||
load_config,
|
||||
save_config,
|
||||
is_reference,
|
||||
):
|
||||
"""Export photos from the Photos database.
|
||||
Export path DEST is required.
|
||||
@@ -1590,6 +1596,7 @@ def export(
|
||||
no_comment=no_comment,
|
||||
has_likes=has_likes,
|
||||
no_likes=no_likes,
|
||||
is_reference=is_reference,
|
||||
)
|
||||
|
||||
if photos:
|
||||
@@ -1865,6 +1872,7 @@ def query(
|
||||
no_comment,
|
||||
has_likes,
|
||||
no_likes,
|
||||
is_reference,
|
||||
):
|
||||
"""Query the Photos database using 1 or more search options;
|
||||
if more than one option is provided, they are treated as "AND"
|
||||
@@ -1887,6 +1895,7 @@ def query(
|
||||
from_date,
|
||||
to_date,
|
||||
label,
|
||||
is_reference,
|
||||
]
|
||||
exclusive = [
|
||||
(favorite, not_favorite),
|
||||
@@ -2002,6 +2011,7 @@ def query(
|
||||
no_comment=no_comment,
|
||||
has_likes=has_likes,
|
||||
no_likes=no_likes,
|
||||
is_reference=is_reference,
|
||||
)
|
||||
|
||||
# below needed for to make CliRunner work for testing
|
||||
@@ -2172,6 +2182,7 @@ def _query(
|
||||
no_comment=False,
|
||||
has_likes=False,
|
||||
no_likes=False,
|
||||
is_reference=False,
|
||||
):
|
||||
"""Run a query against PhotosDB to extract the photos based on user supply criteria used by query and export commands
|
||||
|
||||
@@ -2316,9 +2327,9 @@ def _query(
|
||||
photos = [p for p in photos if not p.hidden]
|
||||
|
||||
if missing:
|
||||
photos = [p for p in photos if p.ismissing]
|
||||
photos = [p for p in photos if not p.path]
|
||||
elif not_missing:
|
||||
photos = [p for p in photos if not p.ismissing]
|
||||
photos = [p for p in photos if p.path]
|
||||
|
||||
if shared:
|
||||
photos = [p for p in photos if p.shared]
|
||||
@@ -2401,6 +2412,9 @@ def _query(
|
||||
elif no_likes:
|
||||
photos = [p for p in photos if not p.likes]
|
||||
|
||||
if is_reference:
|
||||
photos = [p for p in photos if p.isreference]
|
||||
|
||||
return photos
|
||||
|
||||
|
||||
@@ -3760,5 +3774,6 @@ SOFTWARE.
|
||||
click.echo(f"Source code available at: {OSXPHOTOS_URL}")
|
||||
click.echo(license)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli() # pylint: disable=no-value-for-parameter
|
||||
|
||||
@@ -138,6 +138,7 @@ class PhotoInfo:
|
||||
except AttributeError:
|
||||
self._path = None
|
||||
photopath = None
|
||||
# TODO: should path try to return path even if ismissing?
|
||||
if self._info["isMissing"] == 1:
|
||||
return photopath # path would be meaningless until downloaded
|
||||
|
||||
@@ -643,6 +644,11 @@ class PhotoInfo:
|
||||
else:
|
||||
return True if self._info["cloudAssetGUID"] is not None else False
|
||||
|
||||
@property
|
||||
def isreference(self):
|
||||
""" Returns True if photo is a reference (not copied to the Photos library), otherwise False """
|
||||
return self._info["isreference"]
|
||||
|
||||
@property
|
||||
def burst(self):
|
||||
""" Returns True if photo is part of a Burst photo set, otherwise False """
|
||||
@@ -1033,6 +1039,7 @@ class PhotoInfo:
|
||||
"path_live_photo": self.path_live_photo,
|
||||
"iscloudasset": self.iscloudasset,
|
||||
"incloud": self.incloud,
|
||||
"isreference": self.isreference,
|
||||
"date_modified": self.date_modified,
|
||||
"portrait": self.portrait,
|
||||
"screenshot": self.screenshot,
|
||||
|
||||
@@ -889,7 +889,8 @@ class PhotosDB:
|
||||
RKMaster.fileSize,
|
||||
RKVersion.subType,
|
||||
RKVersion.inTrashDate,
|
||||
RKVersion.showInLibrary
|
||||
RKVersion.showInLibrary,
|
||||
RKMaster.fileIsReference
|
||||
FROM RKVersion, RKMaster
|
||||
WHERE RKVersion.masterUuid = RKMaster.uuid"""
|
||||
)
|
||||
@@ -919,8 +920,9 @@ class PhotosDB:
|
||||
RKMaster.originalFileSize,
|
||||
RKVersion.subType,
|
||||
RKVersion.inTrashDate,
|
||||
RKVersion.showInLibrary
|
||||
FROM RKVersion, RKMaster
|
||||
RKVersion.showInLibrary,
|
||||
RKMaster.fileIsReference
|
||||
FROM RKVersion, RKMaster
|
||||
WHERE RKVersion.masterUuid = RKMaster.uuid"""
|
||||
)
|
||||
|
||||
@@ -968,6 +970,7 @@ class PhotosDB:
|
||||
# 40 RKVersion.subType
|
||||
# 41 RKVersion.inTrashDate
|
||||
# 42 RKVersion.showInLibrary -- is item visible in library (e.g. non-selected burst images are not visible)
|
||||
# 43 RKMaster.fileIsReference -- file is reference (imported without copying to Photos library)
|
||||
|
||||
for row in c:
|
||||
uuid = row[0]
|
||||
@@ -1164,6 +1167,10 @@ class PhotosDB:
|
||||
self._dbphotos[uuid]["visibility_state"] = row[42]
|
||||
self._dbphotos[uuid]["visible"] = row[42] == 1
|
||||
|
||||
# file is reference (not copied into Photos library)
|
||||
self._dbphotos[uuid]["isreference"] = row[43] == 1
|
||||
self._dbphotos[uuid]["saved_asset_type"] = None # Photos 5+
|
||||
|
||||
# import session not yet handled for Photos 4
|
||||
self._dbphotos[uuid]["import_session"] = None
|
||||
self._dbphotos[uuid]["import_uuid"] = None
|
||||
@@ -1859,7 +1866,8 @@ class PhotosDB:
|
||||
{depth_state},
|
||||
{asset_table}.ZADJUSTMENTTIMESTAMP,
|
||||
{asset_table}.ZVISIBILITYSTATE,
|
||||
{asset_table}.ZTRASHEDDATE
|
||||
{asset_table}.ZTRASHEDDATE,
|
||||
{asset_table}.ZSAVEDASSETTYPE
|
||||
FROM {asset_table}
|
||||
JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = {asset_table}.Z_PK
|
||||
ORDER BY {asset_table}.ZUUID """
|
||||
@@ -1906,6 +1914,7 @@ class PhotosDB:
|
||||
# 37 ZGENERICASSET.ZADJUSTMENTTIMESTAMP -- when was photo edited?
|
||||
# 38 ZGENERICASSET.ZVISIBILITYSTATE -- 0 if visible, 2 if not (e.g. a burst image)
|
||||
# 39 ZGENERICASSET.ZTRASHEDDATE -- date item placed in the trash or null if not in trash
|
||||
# 40 ZGENERICASSET.ZSAVEDASSETTYPE -- how item imported
|
||||
|
||||
for row in c:
|
||||
uuid = row[0]
|
||||
@@ -2085,6 +2094,14 @@ class PhotosDB:
|
||||
info["visibility_state"] = row[38]
|
||||
info["visible"] = row[38] == 0
|
||||
|
||||
# ZSAVEDASSETTYPE Values:
|
||||
# 3: imported by copying to Photos library
|
||||
# 4: shared iCloud photo
|
||||
# 6: imported by iCloud (e.g. from iPhone)
|
||||
# 10: referenced file (not copied to Photos library)
|
||||
info["saved_asset_type"] = row[40]
|
||||
info["isreference"] = row[40] == 10
|
||||
|
||||
# initialize import session info which will be filled in later
|
||||
# not every photo has an import session so initialize all records now
|
||||
info["import_session"] = None
|
||||
|
||||
Reference in New Issue
Block a user