Fixed bug in --download-missing related to burst images

This commit is contained in:
Rhet Turnbull
2020-03-14 08:54:46 -07:00
parent dc87194eec
commit 1f13ba837f
5 changed files with 22 additions and 5 deletions

View File

@@ -175,7 +175,9 @@ Options:
edited version exists. Edited photo will be edited version exists. Edited photo will be
named in form of "photoname_edited.ext" named in form of "photoname_edited.ext"
--export-bursts If a photo is a burst photo export all --export-bursts If a photo is a burst photo export all
associated burst images in the library. associated burst images in the library. Not
currently compatible with --download-
misssing; see note on --download-missing.
--export-live If a photo is a live photo export the --export-live If a photo is a live photo export the
associated live video component. Live video associated live video component. Live video
will have same name as photo but with .mov will have same name as photo but with .mov
@@ -201,7 +203,10 @@ Options:
exist on disk. This will be slow and will exist on disk. This will be slow and will
require internet connection. This obviously require internet connection. This obviously
only works if the Photos library is synched only works if the Photos library is synched
to iCloud. to iCloud. Note: --download-missing is not
currently compatabile with --export-bursts;
only the primary photo will be exported--
associated burst images will be skipped.
--exiftool Use exiftool to write metadata directly to --exiftool Use exiftool to write metadata directly to
exported photos. To use this option, exported photos. To use this option,
exiftool must be installed and in the path. exiftool must be installed and in the path.

View File

@@ -701,7 +701,8 @@ def query(
@click.option( @click.option(
"--export-bursts", "--export-bursts",
is_flag=True, is_flag=True,
help="If a photo is a burst photo export all associated burst images in the library.", help="If a photo is a burst photo export all associated burst images in the library. "
"Not currently compatible with --download-misssing; see note on --download-missing.",
) )
@click.option( @click.option(
"--export-live", "--export-live",
@@ -734,7 +735,9 @@ def query(
help="Attempt to download missing photos from iCloud. The current implementation uses Applescript " help="Attempt to download missing photos from iCloud. The current implementation uses Applescript "
"to interact with Photos to export the photo which will force Photos to download from iCloud if " "to interact with Photos to export the photo which will force Photos to download from iCloud if "
"the photo does not exist on disk. This will be slow and will require internet connection. " "the photo does not exist on disk. This will be slow and will require internet connection. "
"This obviously only works if the Photos library is synched to iCloud.", "This obviously only works if the Photos library is synched to iCloud. "
"Note: --download-missing is not currently compatabile with --export-bursts; "
"only the primary photo will be exported--associated burst images will be skipped.",
) )
@click.option( @click.option(
"--exiftool", "--exiftool",

View File

@@ -1,3 +1,3 @@
""" version info """ """ version info """
__version__ = "0.22.15" __version__ = "0.22.16"

View File

@@ -663,6 +663,7 @@ class PhotoInfo:
edited=True, edited=True,
live_photo=live_photo, live_photo=live_photo,
timeout=timeout, timeout=timeout,
burst=self.burst,
) )
else: else:
# export original version and not edited # export original version and not edited
@@ -675,6 +676,7 @@ class PhotoInfo:
edited=False, edited=False,
live_photo=live_photo, live_photo=live_photo,
timeout=timeout, timeout=timeout,
burst=self.burst,
) )
if exported is not None: if exported is not None:

View File

@@ -315,6 +315,7 @@ def _export_photo_uuid_applescript(
edited=False, edited=False,
live_photo=False, live_photo=False,
timeout=120, timeout=120,
burst=False,
): ):
""" Export photo to dest path using applescript to control Photos """ Export photo to dest path using applescript to control Photos
If photo is a live photo, exports both the photo and associated .mov file If photo is a live photo, exports both the photo and associated .mov file
@@ -331,6 +332,7 @@ def _export_photo_uuid_applescript(
will raise error if called with both edited and original = True will raise error if called with both edited and original = True
live_photo: (boolean) if True, export associated .mov live photo; default = False live_photo: (boolean) if True, export associated .mov live photo; default = False
timeout: timeout value in seconds; export will fail if applescript run time exceeds timeout timeout: timeout value in seconds; export will fail if applescript run time exceeds timeout
burst: (boolean) set to True if file is a burst image to avoid Photos export error
Returns: list of paths to exported file(s) or None if export failed Returns: list of paths to exported file(s) or None if export failed
Note: For Live Photos, if edited=True, will export a jpeg but not the movie, even if photo Note: For Live Photos, if edited=True, will export a jpeg but not the movie, even if photo
has not been edited. This is due to how Photos Applescript interface works. has not been edited. This is due to how Photos Applescript interface works.
@@ -388,6 +390,7 @@ def _export_photo_uuid_applescript(
# need to find actual filename as sometimes Photos renames JPG to jpeg on export # need to find actual filename as sometimes Photos renames JPG to jpeg on export
# may be more than one file exported (e.g. if Live Photo, Photos exports both .jpeg and .mov) # may be more than one file exported (e.g. if Live Photo, Photos exports both .jpeg and .mov)
# TemporaryDirectory will cleanup on return # TemporaryDirectory will cleanup on return
filename_stem = pathlib.Path(filename).stem
files = glob.glob(os.path.join(tmpdir.name, "*")) files = glob.glob(os.path.join(tmpdir.name, "*"))
exported_paths = [] exported_paths = []
for fname in files: for fname in files:
@@ -396,6 +399,10 @@ def _export_photo_uuid_applescript(
# it's the .mov part of live photo but not requested, so don't export # it's the .mov part of live photo but not requested, so don't export
logging.debug(f"Skipping live photo file {path}") logging.debug(f"Skipping live photo file {path}")
continue continue
if len(files) > 1 and burst and path.stem != filename_stem:
# skip any burst photo that's not the one we asked for
logging.debug(f"Skipping burst photo file {path}")
continue
if filestem: if filestem:
# rename the file based on filestem, keeping original extension # rename the file based on filestem, keeping original extension
dest_new = dest / f"{filestem}{path.suffix}" dest_new = dest / f"{filestem}{path.suffix}"