Added israw, tests for Big Sur

This commit is contained in:
Rhet Turnbull
2020-10-11 08:59:49 -07:00
parent b32f4b8504
commit b5a9794f6b
11 changed files with 133 additions and 52 deletions

View File

@@ -148,7 +148,7 @@ class ExportCommand(click.Command):
formatter.write("\n")
formatter.write_text(
"Note: The number of files reported for export and the number actually exported "
+ "may differ due to live photos, associated RAW images, and edited photos which are reported "
+ "may differ due to live photos, associated raw images, and edited photos which are reported "
+ "in the total photos exported."
)
formatter.write("\n")
@@ -474,7 +474,7 @@ def query_options(f):
o(
"--has-raw",
is_flag=True,
help="Search for photos with both a jpeg and RAW version",
help="Search for photos with both a jpeg and raw version",
),
o(
"--only-movies",
@@ -1183,9 +1183,9 @@ def query(
@click.option(
"--skip-raw",
is_flag=True,
help="Do not export associated RAW images of a RAW/jpeg pair. "
"Note: this does not skip RAW photos if the RAW photo does not have an associated jpeg image "
"(e.g. the RAW file was imported to Photos without a jpeg preview).",
help="Do not export associated raw images of a RAW+JPEG pair. "
"Note: this does not skip raw photos if the raw photo does not have an associated jpeg image "
"(e.g. the raw file was imported to Photos without a jpeg preview).",
)
@click.option(
"--person-keyword",
@@ -1233,7 +1233,7 @@ def query(
@click.option(
"--convert-to-jpeg",
is_flag=True,
help="Convert all non-jpeg images (e.g. RAW, HEIC, PNG, etc) "
help="Convert all non-jpeg images (e.g. raw, HEIC, PNG, etc) "
"to JPEG upon export. Only works if your Mac has a GPU.",
)
@click.option(
@@ -1409,7 +1409,7 @@ def export(
(e.g. search for photos matching all options).
If no query options are provided, all photos will be exported.
By default, all versions of all photos will be exported including edited
versions, live photo movies, burst photos, and associated RAW images.
versions, live photo movies, burst photos, and associated raw images.
See --skip-edited, --skip-live, --skip-bursts, and --skip-raw options
to modify this behavior.
"""
@@ -2058,7 +2058,7 @@ def _query(
photos = [p for p in photos if not p.shared]
if uti:
photos = [p for p in photos if uti in p.uti]
photos = [p for p in photos if uti in p.uti_original]
if burst:
photos = [p for p in photos if p.burst]
@@ -2199,7 +2199,7 @@ def export_photo(
directory: template used to determine output directory
filename_template: template use to determine output file
no_extended_attributes: boolean; if True, exports photo without preserving extended attributes
export_raw: boolean; if True exports RAW image associate with the photo
export_raw: boolean; if True exports raw image associate with the photo
export_edited: boolean; if True exports edited version of photo if there is one
skip_original_if_edited: boolean; if True does not export original if photo has been edited
album_keyword: boolean; if True, exports album names as keywords in metadata

View File

@@ -543,7 +543,10 @@ class PhotoInfo:
""" Returns Uniform Type Identifier (UTI) for the original image
for example: public.jpeg or com.apple.quicktime-movie
"""
return self._info["UTI_original"]
if self._db._db_version <= _PHOTOS_4_VERSION and self._info["has_raw"]:
return self._info["raw_pair_info"]["UTI"]
else:
return self._info["UTI_original"]
@property
def uti_edited(self):
@@ -745,12 +748,17 @@ class PhotoInfo:
@property
def has_raw(self):
""" returns True if photo has an associated RAW image, otherwise False """
""" returns True if photo has an associated raw image (that is, it's a RAW+JPEG pair), otherwise False """
return self._info["has_raw"]
@property
def israw(self):
""" returns True if photo is a raw image. For images with an associated RAW+JPEG pair, see has_raw """
return "raw-image" in self.uti_original
@property
def raw_original(self):
""" returns True if associated RAW image and the RAW image is selected in Photos
""" returns True if associated raw image and the raw image is selected in Photos
via "Use RAW as Original "
otherwise returns False """
return self._info["raw_is_original"]

View File

@@ -1065,6 +1065,17 @@ class PhotosDB:
self._dbphotos[uuid]["cloudAvailable"] = None
self._dbphotos[uuid]["incloud"] = None
# associated RAW image info
self._dbphotos[uuid]["has_raw"] = True if row[25] == 7 else False
self._dbphotos[uuid]["UTI_raw"] = None
self._dbphotos[uuid]["raw_data_length"] = None
self._dbphotos[uuid]["raw_info"] = None
self._dbphotos[uuid]["resource_type"] = None # Photos 5
self._dbphotos[uuid]["datastore_subtype"] = None # Photos 5
self._dbphotos[uuid]["raw_master_uuid"] = row[29]
self._dbphotos[uuid]["non_raw_master_uuid"] = row[30]
self._dbphotos[uuid]["alt_master_uuid"] = row[31]
# original resource choice (e.g. RAW or jpeg)
# In Photos 5+, original_resource_choice set from:
# ZADDITIONALASSETATTRIBUTES.ZORIGINALRESOURCECHOICE
@@ -1077,19 +1088,12 @@ class PhotosDB:
# 64 = TIFF
# 2048 = PNG
# 32768 = HIEC
self._dbphotos[uuid]["original_resource_choice"] = 1 if row[40] == 16 else 0
self._dbphotos[uuid]["raw_is_original"] = True if row[40] == 16 else False
# associated RAW image info
self._dbphotos[uuid]["has_raw"] = True if row[25] == 7 else False
self._dbphotos[uuid]["UTI_raw"] = None
self._dbphotos[uuid]["raw_data_length"] = None
self._dbphotos[uuid]["raw_info"] = None
self._dbphotos[uuid]["resource_type"] = None # Photos 5
self._dbphotos[uuid]["datastore_subtype"] = None # Photos 5
self._dbphotos[uuid]["raw_master_uuid"] = row[29]
self._dbphotos[uuid]["non_raw_master_uuid"] = row[30]
self._dbphotos[uuid]["alt_master_uuid"] = row[31]
self._dbphotos[uuid]["original_resource_choice"] = (
1 if row[40] == 16 and self._dbphotos[uuid]["has_raw"] else 0
)
self._dbphotos[uuid]["raw_is_original"] = bool(
self._dbphotos[uuid]["original_resource_choice"]
)
# recently deleted items
self._dbphotos[uuid]["intrash"] = True if row[32] == 1 else False
@@ -2107,28 +2111,27 @@ class PhotosDB:
WHERE ZDATASTORESUBTYPE = 1 OR ZDATASTORESUBTYPE = 3 """
)
# Order of results:
# 0 {asset_table}.ZUUID,
# 1 ZINTERNALRESOURCE.ZLOCALAVAILABILITY,
# 2 ZINTERNALRESOURCE.ZREMOTEAVAILABILITY,
# 3 ZINTERNALRESOURCE.ZDATASTORESUBTYPE,
# 4 ZINTERNALRESOURCE.ZUNIFORMTYPEIDENTIFIER,
# 5 ZUNIFORMTYPEIDENTIFIER.ZIDENTIFIER
for row in c:
uuid = row[0]
if uuid in self._dbphotos:
# and self._dbphotos[uuid]["isMissing"] is None:
# logging.warning(f"uuid={uuid}, {row[1]}, {row[2]} {row[3]}")
self._dbphotos[uuid]["localAvailability"] = row[1]
self._dbphotos[uuid]["remoteAvailability"] = row[2]
if row[3] == 1:
self._dbphotos[uuid]["UTI_original"] = row[5]
# old = self._dbphotos[uuid]["isMissing"]
if row[1] != 1:
self._dbphotos[uuid]["isMissing"] = 1
else:
self._dbphotos[uuid]["isMissing"] = 0
# if old is not None and old != self._dbphotos[uuid]["isMissing"]:
# logging.warning(
# f"{uuid} isMissing changed: {old} {self._dbphotos[uuid]['isMissing']}"
# )
# get information on local/remote availability
c.execute(
f""" SELECT {asset_table}.ZUUID,
@@ -2142,22 +2145,14 @@ class PhotosDB:
for row in c:
uuid = row[0]
if uuid in self._dbphotos:
# logging.warning(f"uuid={uuid}, {row[1]}, {row[2]}")
self._dbphotos[uuid]["localAvailability"] = row[1]
self._dbphotos[uuid]["remoteAvailability"] = row[2]
# old = self._dbphotos[uuid]["isMissing"]
if row[1] != 1:
self._dbphotos[uuid]["isMissing"] = 1
else:
self._dbphotos[uuid]["isMissing"] = 0
# if old is not None and old != self._dbphotos[uuid]["isMissing"]:
# logging.warning(
# f"{uuid} isMissing changed: {old} {self._dbphotos[uuid]['isMissing']}"
# )
# get information about cloud sync state
c.execute(
f""" SELECT