Refactored PhotoInfo.export2
This commit is contained in:
parent
bb96c35672
commit
d7a9ad1d0a
@ -817,139 +817,21 @@ def export2(
|
|||||||
)
|
)
|
||||||
all_results += results
|
all_results += results
|
||||||
else:
|
else:
|
||||||
# TODO: move this big if/else block to separate functions
|
self._export_photo_with_photos_export(
|
||||||
# e.g. _export_with_photos_export or such
|
dest,
|
||||||
# use_photo_export
|
filename,
|
||||||
# export live_photo .mov file?
|
all_results,
|
||||||
live_photo = True if live_photo and self.live_photo else False
|
fileutil,
|
||||||
if edited or self.shared:
|
use_photokit=use_photokit,
|
||||||
# exported edited version and not original
|
|
||||||
# shared photos (in shared albums) show up as not having adjustments (not edited)
|
|
||||||
# but Photos is unable to export the "original" as only a jpeg copy is shared in iCloud
|
|
||||||
# so tell Photos to export the current version in this case
|
|
||||||
if filename:
|
|
||||||
# use filename stem provided
|
|
||||||
filestem = dest.stem
|
|
||||||
else:
|
|
||||||
# didn't get passed a filename, add _edited
|
|
||||||
filestem = f"{dest.stem}{edited_identifier}"
|
|
||||||
uti = self.uti_edited if edited and self.uti_edited else self.uti
|
|
||||||
ext = get_preferred_uti_extension(uti)
|
|
||||||
dest = dest.parent / f"{filestem}{ext}"
|
|
||||||
|
|
||||||
if use_photokit:
|
|
||||||
photolib = PhotoLibrary()
|
|
||||||
photo = None
|
|
||||||
try:
|
|
||||||
photo = photolib.fetch_uuid(self.uuid)
|
|
||||||
except PhotoKitFetchFailed as e:
|
|
||||||
# if failed to find UUID, might be a burst photo
|
|
||||||
if self.burst and self._info["burstUUID"]:
|
|
||||||
bursts = photolib.fetch_burst_uuid(
|
|
||||||
self._info["burstUUID"], all=True
|
|
||||||
)
|
|
||||||
# PhotoKit UUIDs may contain "/L0/001" so only look at beginning
|
|
||||||
photo = [p for p in bursts if p.uuid.startswith(self.uuid)]
|
|
||||||
photo = photo[0] if photo else None
|
|
||||||
if not photo:
|
|
||||||
all_results.error.append(
|
|
||||||
(
|
|
||||||
str(dest),
|
|
||||||
f"PhotoKitFetchFailed exception exporting photo {self.uuid}: {e} ({lineno(__file__)})",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if photo:
|
|
||||||
if not dry_run:
|
|
||||||
try:
|
|
||||||
exported = photo.export(
|
|
||||||
dest.parent, dest.name, version=PHOTOS_VERSION_CURRENT
|
|
||||||
)
|
|
||||||
all_results.exported.extend(exported)
|
|
||||||
except Exception as e:
|
|
||||||
all_results.error.append(
|
|
||||||
(str(dest), f"{e} ({lineno(__file__)})")
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# dry_run, don't actually export
|
|
||||||
all_results.exported.append(str(dest))
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
exported = _export_photo_uuid_applescript(
|
|
||||||
self.uuid,
|
|
||||||
dest.parent,
|
|
||||||
filestem=filestem,
|
|
||||||
original=False,
|
|
||||||
edited=True,
|
|
||||||
live_photo=live_photo,
|
|
||||||
timeout=timeout,
|
|
||||||
burst=self.burst,
|
|
||||||
dry_run=dry_run,
|
dry_run=dry_run,
|
||||||
)
|
|
||||||
all_results.exported.extend(exported)
|
|
||||||
except ExportError as e:
|
|
||||||
all_results.error.append((str(dest), f"{e} ({lineno(__file__)})"))
|
|
||||||
else:
|
|
||||||
# export original version and not edited
|
|
||||||
filestem = dest.stem
|
|
||||||
if use_photokit:
|
|
||||||
photolib = PhotoLibrary()
|
|
||||||
photo = None
|
|
||||||
try:
|
|
||||||
photo = photolib.fetch_uuid(self.uuid)
|
|
||||||
except PhotoKitFetchFailed:
|
|
||||||
# if failed to find UUID, might be a burst photo
|
|
||||||
if self.burst and self._info["burstUUID"]:
|
|
||||||
bursts = photolib.fetch_burst_uuid(
|
|
||||||
self._info["burstUUID"], all=True
|
|
||||||
)
|
|
||||||
# PhotoKit UUIDs may contain "/L0/001" so only look at beginning
|
|
||||||
photo = [p for p in bursts if p.uuid.startswith(self.uuid)]
|
|
||||||
photo = photo[0] if photo else None
|
|
||||||
if photo:
|
|
||||||
if not dry_run:
|
|
||||||
try:
|
|
||||||
exported = photo.export(
|
|
||||||
dest.parent, dest.name, version=PHOTOS_VERSION_ORIGINAL
|
|
||||||
)
|
|
||||||
all_results.exported.extend(exported)
|
|
||||||
except Exception as e:
|
|
||||||
all_results.error.append(
|
|
||||||
(str(dest), f"{e} ({lineno(__file__)})")
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# dry_run, don't actually export
|
|
||||||
all_results.exported.append(str(dest))
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
exported = _export_photo_uuid_applescript(
|
|
||||||
self.uuid,
|
|
||||||
dest.parent,
|
|
||||||
filestem=filestem,
|
|
||||||
original=True,
|
|
||||||
edited=False,
|
|
||||||
live_photo=live_photo,
|
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
burst=self.burst,
|
jpeg_ext=jpeg_ext,
|
||||||
dry_run=dry_run,
|
touch_file=touch_file,
|
||||||
|
update=update,
|
||||||
|
live_photo=live_photo,
|
||||||
|
edited=edited,
|
||||||
|
edited_identifier=edited_identifier,
|
||||||
)
|
)
|
||||||
all_results.exported.extend(exported)
|
|
||||||
except ExportError as e:
|
|
||||||
all_results.error.append((str(dest), f"{e} ({lineno(__file__)})"))
|
|
||||||
if all_results.exported:
|
|
||||||
if jpeg_ext:
|
|
||||||
# use_photos_export (both PhotoKit and AppleScript) don't use the
|
|
||||||
# file extension provided (instead they use extension for UTI)
|
|
||||||
# so if jpeg_ext is set, rename any non-conforming jpegs
|
|
||||||
all_results.exported = rename_jpeg_files(
|
|
||||||
all_results.exported, jpeg_ext, fileutil
|
|
||||||
)
|
|
||||||
if touch_file:
|
|
||||||
for exported_file in all_results.exported:
|
|
||||||
all_results.touched.append(exported_file)
|
|
||||||
ts = int(self.date.timestamp())
|
|
||||||
fileutil.utime(exported_file, (ts, ts))
|
|
||||||
if update:
|
|
||||||
all_results.new.extend(all_results.exported)
|
|
||||||
|
|
||||||
# export metadata
|
# export metadata
|
||||||
sidecars = []
|
sidecars = []
|
||||||
@ -1207,6 +1089,156 @@ def export2(
|
|||||||
return all_results
|
return all_results
|
||||||
|
|
||||||
|
|
||||||
|
def _export_photo_with_photos_export(
|
||||||
|
self,
|
||||||
|
dest,
|
||||||
|
filename,
|
||||||
|
all_results,
|
||||||
|
fileutil,
|
||||||
|
use_photokit=None,
|
||||||
|
dry_run=None,
|
||||||
|
timeout=None,
|
||||||
|
jpeg_ext=None,
|
||||||
|
touch_file=None,
|
||||||
|
update=None,
|
||||||
|
live_photo=None,
|
||||||
|
edited=None,
|
||||||
|
edited_identifier=None,
|
||||||
|
):
|
||||||
|
# e.g. _export_with_photos_export or such
|
||||||
|
# use_photo_export
|
||||||
|
# export live_photo .mov file?
|
||||||
|
live_photo = True if live_photo and self.live_photo else False
|
||||||
|
if edited or self.shared:
|
||||||
|
# exported edited version and not original
|
||||||
|
# shared photos (in shared albums) show up as not having adjustments (not edited)
|
||||||
|
# but Photos is unable to export the "original" as only a jpeg copy is shared in iCloud
|
||||||
|
# so tell Photos to export the current version in this case
|
||||||
|
if filename:
|
||||||
|
# use filename stem provided
|
||||||
|
filestem = dest.stem
|
||||||
|
else:
|
||||||
|
# didn't get passed a filename, add _edited
|
||||||
|
filestem = f"{dest.stem}{edited_identifier}"
|
||||||
|
uti = self.uti_edited if edited and self.uti_edited else self.uti
|
||||||
|
ext = get_preferred_uti_extension(uti)
|
||||||
|
dest = dest.parent / f"{filestem}{ext}"
|
||||||
|
|
||||||
|
if use_photokit:
|
||||||
|
photolib = PhotoLibrary()
|
||||||
|
photo = None
|
||||||
|
try:
|
||||||
|
photo = photolib.fetch_uuid(self.uuid)
|
||||||
|
except PhotoKitFetchFailed as e:
|
||||||
|
# if failed to find UUID, might be a burst photo
|
||||||
|
if self.burst and self._info["burstUUID"]:
|
||||||
|
bursts = photolib.fetch_burst_uuid(
|
||||||
|
self._info["burstUUID"], all=True
|
||||||
|
)
|
||||||
|
# PhotoKit UUIDs may contain "/L0/001" so only look at beginning
|
||||||
|
photo = [p for p in bursts if p.uuid.startswith(self.uuid)]
|
||||||
|
photo = photo[0] if photo else None
|
||||||
|
if not photo:
|
||||||
|
all_results.error.append(
|
||||||
|
(
|
||||||
|
str(dest),
|
||||||
|
f"PhotoKitFetchFailed exception exporting photo {self.uuid}: {e} ({lineno(__file__)})",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if photo:
|
||||||
|
if not dry_run:
|
||||||
|
try:
|
||||||
|
exported = photo.export(
|
||||||
|
dest.parent, dest.name, version=PHOTOS_VERSION_CURRENT
|
||||||
|
)
|
||||||
|
all_results.exported.extend(exported)
|
||||||
|
except Exception as e:
|
||||||
|
all_results.error.append(
|
||||||
|
(str(dest), f"{e} ({lineno(__file__)})")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# dry_run, don't actually export
|
||||||
|
all_results.exported.append(str(dest))
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
exported = _export_photo_uuid_applescript(
|
||||||
|
self.uuid,
|
||||||
|
dest.parent,
|
||||||
|
filestem=filestem,
|
||||||
|
original=False,
|
||||||
|
edited=True,
|
||||||
|
live_photo=live_photo,
|
||||||
|
timeout=timeout,
|
||||||
|
burst=self.burst,
|
||||||
|
dry_run=dry_run,
|
||||||
|
)
|
||||||
|
all_results.exported.extend(exported)
|
||||||
|
except ExportError as e:
|
||||||
|
all_results.error.append((str(dest), f"{e} ({lineno(__file__)})"))
|
||||||
|
else:
|
||||||
|
# export original version and not edited
|
||||||
|
filestem = dest.stem
|
||||||
|
if use_photokit:
|
||||||
|
photolib = PhotoLibrary()
|
||||||
|
photo = None
|
||||||
|
try:
|
||||||
|
photo = photolib.fetch_uuid(self.uuid)
|
||||||
|
except PhotoKitFetchFailed:
|
||||||
|
# if failed to find UUID, might be a burst photo
|
||||||
|
if self.burst and self._info["burstUUID"]:
|
||||||
|
bursts = photolib.fetch_burst_uuid(
|
||||||
|
self._info["burstUUID"], all=True
|
||||||
|
)
|
||||||
|
# PhotoKit UUIDs may contain "/L0/001" so only look at beginning
|
||||||
|
photo = [p for p in bursts if p.uuid.startswith(self.uuid)]
|
||||||
|
photo = photo[0] if photo else None
|
||||||
|
if photo:
|
||||||
|
if not dry_run:
|
||||||
|
try:
|
||||||
|
exported = photo.export(
|
||||||
|
dest.parent, dest.name, version=PHOTOS_VERSION_ORIGINAL
|
||||||
|
)
|
||||||
|
all_results.exported.extend(exported)
|
||||||
|
except Exception as e:
|
||||||
|
all_results.error.append(
|
||||||
|
(str(dest), f"{e} ({lineno(__file__)})")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# dry_run, don't actually export
|
||||||
|
all_results.exported.append(str(dest))
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
exported = _export_photo_uuid_applescript(
|
||||||
|
self.uuid,
|
||||||
|
dest.parent,
|
||||||
|
filestem=filestem,
|
||||||
|
original=True,
|
||||||
|
edited=False,
|
||||||
|
live_photo=live_photo,
|
||||||
|
timeout=timeout,
|
||||||
|
burst=self.burst,
|
||||||
|
dry_run=dry_run,
|
||||||
|
)
|
||||||
|
all_results.exported.extend(exported)
|
||||||
|
except ExportError as e:
|
||||||
|
all_results.error.append((str(dest), f"{e} ({lineno(__file__)})"))
|
||||||
|
if all_results.exported:
|
||||||
|
if jpeg_ext:
|
||||||
|
# use_photos_export (both PhotoKit and AppleScript) don't use the
|
||||||
|
# file extension provided (instead they use extension for UTI)
|
||||||
|
# so if jpeg_ext is set, rename any non-conforming jpegs
|
||||||
|
all_results.exported = rename_jpeg_files(
|
||||||
|
all_results.exported, jpeg_ext, fileutil
|
||||||
|
)
|
||||||
|
if touch_file:
|
||||||
|
for exported_file in all_results.exported:
|
||||||
|
all_results.touched.append(exported_file)
|
||||||
|
ts = int(self.date.timestamp())
|
||||||
|
fileutil.utime(exported_file, (ts, ts))
|
||||||
|
if update:
|
||||||
|
all_results.new.extend(all_results.exported)
|
||||||
|
|
||||||
|
|
||||||
def _export_photo(
|
def _export_photo(
|
||||||
self,
|
self,
|
||||||
src,
|
src,
|
||||||
|
|||||||
@ -61,6 +61,7 @@ class PhotoInfo:
|
|||||||
_export_photo,
|
_export_photo,
|
||||||
_exiftool_dict,
|
_exiftool_dict,
|
||||||
_exiftool_json_sidecar,
|
_exiftool_json_sidecar,
|
||||||
|
_export_photo_with_photos_export,
|
||||||
_get_exif_keywords,
|
_get_exif_keywords,
|
||||||
_get_exif_persons,
|
_get_exif_persons,
|
||||||
_write_exif_data,
|
_write_exif_data,
|
||||||
|
|||||||
@ -10,9 +10,9 @@ import json
|
|||||||
import osxphotos
|
import osxphotos
|
||||||
|
|
||||||
UUID = [
|
UUID = [
|
||||||
"C8EAF50A-D891-4E0C-8086-C417E1284153",
|
"DC09F4D8-6173-452D-AC15-725C8D7C185E",
|
||||||
"71DFB4C3-E868-4BE4-906E-D96BD8692D7E",
|
"AFECD4AB-937C-46AF-A79B-9C9A38AA42B1",
|
||||||
"2C151013-5BBA-4D00-B70F-1C9420418B86",
|
"A1C36260-92CD-47E2-927A-35DAF16D7882",
|
||||||
]
|
]
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -115,14 +115,14 @@ UUID_DICT = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UUID_DICT_LOCAL = {
|
UUID_DICT_LOCAL = {
|
||||||
"not_visible": "ABF00253-78E7-4FD6-953B-709307CD489D",
|
"not_visible": "4A836160-51B2-4E32-907D-ECDDB2CEC657", # IMG_9815.JPG
|
||||||
"burst": "44AF1FCA-AC2D-4FA5-B288-E67DC18F9CA8",
|
"burst": "9A5B4CE6-6A9F-4917-95D4-1C98D14FCE4F", # IMG_9812.JPG
|
||||||
"burst_key": "9F90DC00-AAAF-4A05-9A65-61FEEE0D67F2",
|
"burst_key": "9A5B4CE6-6A9F-4917-95D4-1C98D14FCE4F", # IMG_9812.JPG
|
||||||
"burst_not_key": "38F8F30C-FF6D-49DA-8092-18497F1D6628",
|
"burst_not_key": "4A836160-51B2-4E32-907D-ECDDB2CEC657", # IMG_9815.JPG
|
||||||
"burst_selected": "38F8F30C-FF6D-49DA-8092-18497F1D6628",
|
"burst_selected": "75154738-83AA-4DCD-A913-632D5D1C0FEE", # IMG_9814.JPG
|
||||||
"burst_not_selected": "A385FA13-DF8E-482F-A8C5-970EDDF54C2F",
|
"burst_not_selected": "89E235DD-B9AC-4E8D-BDA2-986981CA7582", # IMG_9813.JPG
|
||||||
"burst_default": "964F457D-5FFC-47B9-BEAD-56B0A83FEF63",
|
"burst_default": "F5E6BD24-B493-44E9-BDA2-7AD9D2CC8C9D", # IMG_9816.JPG
|
||||||
"burst_not_default": "A385FA13-DF8E-482F-A8C5-970EDDF54C2F",
|
"burst_not_default": "75154738-83AA-4DCD-A913-632D5D1C0FEE", # IMG_9814.JPG
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID_PUMPKIN_FARM = [
|
UUID_PUMPKIN_FARM = [
|
||||||
|
|||||||
@ -20,7 +20,7 @@ NAMES_DICT = {
|
|||||||
"heic": "IMG_3092.jpeg"
|
"heic": "IMG_3092.jpeg"
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID_LIVE_HEIC = "612CE30B-3D8F-417A-9B14-EC42CBA10ACC"
|
UUID_LIVE_HEIC = "8EC216A2-0032-4934-BD3F-04C6259B3304"
|
||||||
NAMES_LIVE_HEIC = [
|
NAMES_LIVE_HEIC = [
|
||||||
"IMG_3259.jpeg",
|
"IMG_3259.jpeg",
|
||||||
"IMG_3259.mov"
|
"IMG_3259.mov"
|
||||||
|
|||||||
@ -24,35 +24,35 @@ pytestmark = pytest.mark.skipif(
|
|||||||
|
|
||||||
UUID_DICT = {
|
UUID_DICT = {
|
||||||
"plain_photo": {
|
"plain_photo": {
|
||||||
"uuid": "A8D646C3-89A9-4D74-8001-4EB46BA55B94",
|
"uuid": "C6C712C5-9316-408D-A3C3-125661422DA9",
|
||||||
"filename": "IMG_8844.JPG",
|
"filename": "IMG_8844.JPG",
|
||||||
},
|
},
|
||||||
"hdr": {"uuid": "DA87C6FF-60E8-4DCB-A21D-9C57595667F1", "filename": "IMG_6162.JPG"},
|
"hdr": {"uuid": "DD641004-4E37-4233-AF31-CAA0896490B2", "filename": "IMG_6162.JPG"},
|
||||||
"selfie": {
|
"selfie": {
|
||||||
"uuid": "316AEBE0-971D-4A33-833C-6BDBFF83469B",
|
"uuid": "C925CFDC-FF2B-4E71-AC9D-C669B6453A8B",
|
||||||
"filename": "IMG_1929.JPG",
|
"filename": "IMG_1929.JPG",
|
||||||
},
|
},
|
||||||
"video": {
|
"video": {
|
||||||
"uuid": "5814D9DE-FAB6-473A-9C9A-5A73C6DD1AF5",
|
"uuid": "F4430659-7B17-487E-8029-8C1ABEBE23DF",
|
||||||
"filename": "IMG_9411.TRIM.MOV",
|
"filename": "IMG_9411.TRIM.MOV",
|
||||||
},
|
},
|
||||||
"hasadjustments": {
|
"hasadjustments": {
|
||||||
"uuid": "2B2D5434-6D31-49E2-BF47-B973D34A317B",
|
"uuid": "2F252D2C-C9DE-4BE1-8610-9F968C634D3D",
|
||||||
"filename": "IMG_2860.JPG",
|
"filename": "IMG_2860.JPG",
|
||||||
"adjusted_size": 3012634,
|
"adjusted_size": 3012634,
|
||||||
"unadjusted_size": 2580058,
|
"unadjusted_size": 2580058,
|
||||||
},
|
},
|
||||||
"slow_mo": {
|
"slow_mo": {
|
||||||
"uuid": "DAABC6D9-1FBA-4485-AA39-0A2B100300B1",
|
"uuid": "160447F8-4EB0-4FAE-A26A-3D32EA698F75",
|
||||||
"filename": "IMG_4055.MOV",
|
"filename": "IMG_4055.MOV",
|
||||||
},
|
},
|
||||||
"live_photo": {
|
"live_photo": {
|
||||||
"uuid": "612CE30B-3D8F-417A-9B14-EC42CBA10ACC",
|
"uuid": "8EC216A2-0032-4934-BD3F-04C6259B3304",
|
||||||
"filename": "IMG_3259.HEIC",
|
"filename": "IMG_3259.HEIC",
|
||||||
"filename_video": "IMG_3259.mov",
|
"filename_video": "IMG_3259.mov",
|
||||||
},
|
},
|
||||||
"burst": {
|
"burst": {
|
||||||
"uuid": "CD97EC84-71F0-40C6-BAC1-2BABEE305CAC",
|
"uuid": "CDE4E5D9-1428-41E6-8569-EC0C45FD8E5A",
|
||||||
"filename": "IMG_8196.JPG",
|
"filename": "IMG_8196.JPG",
|
||||||
"burst_selected": 4,
|
"burst_selected": 4,
|
||||||
"burst_all": 5,
|
"burst_all": 5,
|
||||||
@ -106,7 +106,6 @@ def test_burst():
|
|||||||
assert photo.burstid
|
assert photo.burstid
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# def test_selfie():
|
# def test_selfie():
|
||||||
# """ test selfie """
|
# """ test selfie """
|
||||||
# uuid = UUID_DICT["selfie"]["uuid"]
|
# uuid = UUID_DICT["selfie"]["uuid"]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user