Added --preview-if-missing, #446
This commit is contained in:
13
README.md
13
README.md
@@ -891,7 +891,15 @@ Options:
|
|||||||
|
|
||||||
--preview Export preview image generated by Photos. This
|
--preview Export preview image generated by Photos. This
|
||||||
is a lower-resolution image used by Photos to
|
is a lower-resolution image used by Photos to
|
||||||
quickly preview the image.
|
quickly preview the image. See also --preview-
|
||||||
|
suffix and --preview-if-missing.
|
||||||
|
|
||||||
|
--preview-if-missing Export preview image generated by Photos if
|
||||||
|
the actual photo file is missing from the
|
||||||
|
library. This may be helpful if photos were
|
||||||
|
not copied to the Photos library and the
|
||||||
|
original photo is missing. See also --preview-
|
||||||
|
suffix and --preview.
|
||||||
|
|
||||||
--preview-suffix SUFFIX Optional suffix template for naming preview
|
--preview-suffix SUFFIX Optional suffix template for naming preview
|
||||||
photos. Default name for preview photos is in
|
photos. Default name for preview photos is in
|
||||||
@@ -900,7 +908,8 @@ Options:
|
|||||||
photo would be named 'photoname_low_res.ext'.
|
photo would be named 'photoname_low_res.ext'.
|
||||||
The default suffix is '_preview'. Multi-value
|
The default suffix is '_preview'. Multi-value
|
||||||
templates (see Templating System) are not
|
templates (see Templating System) are not
|
||||||
permitted with --preview-suffix.
|
permitted with --preview-suffix. See also
|
||||||
|
--preview and --preview-if-missing.
|
||||||
|
|
||||||
--download-missing Attempt to download missing photos from
|
--download-missing Attempt to download missing photos from
|
||||||
iCloud. The current implementation uses
|
iCloud. The current implementation uses
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
""" version info """
|
""" version info """
|
||||||
|
|
||||||
__version__ = "0.42.57"
|
__version__ = "0.42.58"
|
||||||
|
|||||||
189
osxphotos/cli.py
189
osxphotos/cli.py
@@ -709,7 +709,15 @@ def cli(ctx, db, json_, debug):
|
|||||||
"--preview",
|
"--preview",
|
||||||
is_flag=True,
|
is_flag=True,
|
||||||
help="Export preview image generated by Photos. "
|
help="Export preview image generated by Photos. "
|
||||||
"This is a lower-resolution image used by Photos to quickly preview the image.",
|
"This is a lower-resolution image used by Photos to quickly preview the image. "
|
||||||
|
"See also --preview-suffix and --preview-if-missing.",
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
"--preview-if-missing",
|
||||||
|
is_flag=True,
|
||||||
|
help="Export preview image generated by Photos if the actual photo file is missing from the library. "
|
||||||
|
"This may be helpful if photos were not copied to the Photos library and the original photo is missing. "
|
||||||
|
"See also --preview-suffix and --preview.",
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"--preview-suffix",
|
"--preview-suffix",
|
||||||
@@ -717,7 +725,8 @@ def cli(ctx, db, json_, debug):
|
|||||||
help="Optional suffix template for naming preview photos. Default name for preview photos is in form "
|
help="Optional suffix template for naming preview photos. Default name for preview photos is in form "
|
||||||
f"'photoname{DEFAULT_PREVIEW_SUFFIX}.ext'. For example, with '--preview-suffix _low_res', the preview photo "
|
f"'photoname{DEFAULT_PREVIEW_SUFFIX}.ext'. For example, with '--preview-suffix _low_res', the preview photo "
|
||||||
f"would be named 'photoname_low_res.ext'. The default suffix is '{DEFAULT_PREVIEW_SUFFIX}'. "
|
f"would be named 'photoname_low_res.ext'. The default suffix is '{DEFAULT_PREVIEW_SUFFIX}'. "
|
||||||
"Multi-value templates (see Templating System) are not permitted with --preview-suffix.",
|
"Multi-value templates (see Templating System) are not permitted with --preview-suffix. "
|
||||||
|
"See also --preview and --preview-if-missing.",
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"--download-missing",
|
"--download-missing",
|
||||||
@@ -1180,6 +1189,7 @@ def export(
|
|||||||
post_function,
|
post_function,
|
||||||
preview,
|
preview,
|
||||||
preview_suffix,
|
preview_suffix,
|
||||||
|
preview_if_missing,
|
||||||
):
|
):
|
||||||
"""Export photos from the Photos database.
|
"""Export photos from the Photos database.
|
||||||
Export path DEST is required.
|
Export path DEST is required.
|
||||||
@@ -1342,6 +1352,7 @@ def export(
|
|||||||
post_function = cfg.post_function
|
post_function = cfg.post_function
|
||||||
preview = cfg.preview
|
preview = cfg.preview
|
||||||
preview_suffix = cfg.preview_suffix
|
preview_suffix = cfg.preview_suffix
|
||||||
|
preview_if_missing = cfg.preview_if_missing
|
||||||
|
|
||||||
# config file might have changed verbose
|
# config file might have changed verbose
|
||||||
VERBOSE = bool(verbose)
|
VERBOSE = bool(verbose)
|
||||||
@@ -1753,6 +1764,7 @@ def export(
|
|||||||
export_dir=dest,
|
export_dir=dest,
|
||||||
export_preview=preview,
|
export_preview=preview,
|
||||||
preview_suffix=preview_suffix,
|
preview_suffix=preview_suffix,
|
||||||
|
preview_if_missing=preview_if_missing,
|
||||||
)
|
)
|
||||||
|
|
||||||
if post_function:
|
if post_function:
|
||||||
@@ -2409,6 +2421,7 @@ def export_photo(
|
|||||||
export_dir=None,
|
export_dir=None,
|
||||||
export_preview=False,
|
export_preview=False,
|
||||||
preview_suffix=None,
|
preview_suffix=None,
|
||||||
|
preview_if_missing=False,
|
||||||
):
|
):
|
||||||
"""Helper function for export that does the actual export
|
"""Helper function for export that does the actual export
|
||||||
|
|
||||||
@@ -2452,6 +2465,7 @@ def export_photo(
|
|||||||
export_dir: top-level export directory for {export_dir} template
|
export_dir: top-level export directory for {export_dir} template
|
||||||
export_preview: export the preview image generated by Photos
|
export_preview: export the preview image generated by Photos
|
||||||
preview_suffix: str, template to use as suffix for preview images
|
preview_suffix: str, template to use as suffix for preview images
|
||||||
|
preview_if_missing: bool, export preview if original is missing
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list of path(s) of exported photo or None if photo was missing
|
list of path(s) of exported photo or None if photo was missing
|
||||||
@@ -2598,6 +2612,7 @@ def export_photo(
|
|||||||
export_dir=export_dir,
|
export_dir=export_dir,
|
||||||
export_preview=export_preview,
|
export_preview=export_preview,
|
||||||
preview_suffix=rendered_preview_suffix,
|
preview_suffix=rendered_preview_suffix,
|
||||||
|
preview_if_missing=preview_if_missing,
|
||||||
)
|
)
|
||||||
|
|
||||||
if export_edited and photo.hasadjustments:
|
if export_edited and photo.hasadjustments:
|
||||||
@@ -2682,6 +2697,7 @@ def export_photo(
|
|||||||
export_dir=export_dir,
|
export_dir=export_dir,
|
||||||
export_preview=not export_original and export_preview,
|
export_preview=not export_original and export_preview,
|
||||||
preview_suffix=rendered_preview_suffix,
|
preview_suffix=rendered_preview_suffix,
|
||||||
|
preview_if_missing=preview_if_missing,
|
||||||
)
|
)
|
||||||
|
|
||||||
return results
|
return results
|
||||||
@@ -2759,9 +2775,9 @@ def export_photo_with_template(
|
|||||||
export_dir,
|
export_dir,
|
||||||
export_preview,
|
export_preview,
|
||||||
preview_suffix,
|
preview_suffix,
|
||||||
|
preview_if_missing,
|
||||||
):
|
):
|
||||||
"""Evaluate directory template then export photo to each directory"""
|
"""Evaluate directory template then export photo to each directory"""
|
||||||
|
|
||||||
results = ExportResults()
|
results = ExportResults()
|
||||||
|
|
||||||
dest_paths = get_dirnames_from_template(
|
dest_paths = get_dirnames_from_template(
|
||||||
@@ -2770,17 +2786,18 @@ def export_photo_with_template(
|
|||||||
|
|
||||||
# export the photo to each path in dest_paths
|
# export the photo to each path in dest_paths
|
||||||
for dest_path in dest_paths:
|
for dest_path in dest_paths:
|
||||||
# TODO: if --skip-original-if-edited, it's possible edited version is on disk but
|
|
||||||
# original is missing, in which case we should download the edited version
|
|
||||||
if export_original:
|
if export_original:
|
||||||
if missing:
|
if missing and not preview_if_missing:
|
||||||
space = " " if not verbose else ""
|
space = " " if not verbose else ""
|
||||||
verbose_(
|
verbose_(
|
||||||
f"{space}Skipping missing photo {photo.original_filename} ({photo.uuid})"
|
f"{space}Skipping missing photo {photo.original_filename} ({photo.uuid})"
|
||||||
)
|
)
|
||||||
results.missing.append(str(pathlib.Path(dest_path) / filename))
|
results.missing.append(str(pathlib.Path(dest_path) / filename))
|
||||||
continue
|
elif (
|
||||||
elif photo.intrash and (not photo.path or use_photos_export):
|
photo.intrash
|
||||||
|
and (not photo.path or use_photos_export)
|
||||||
|
and not preview_if_missing
|
||||||
|
):
|
||||||
# skip deleted files if they're missing or using use_photos_export
|
# skip deleted files if they're missing or using use_photos_export
|
||||||
# as AppleScript/PhotoKit cannot export deleted photos
|
# as AppleScript/PhotoKit cannot export deleted photos
|
||||||
space = " " if not verbose else ""
|
space = " " if not verbose else ""
|
||||||
@@ -2794,12 +2811,16 @@ def export_photo_with_template(
|
|||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
# exporting the edited version
|
# exporting the edited version
|
||||||
if missing:
|
if missing and not preview_if_missing:
|
||||||
space = " " if not verbose else ""
|
space = " " if not verbose else ""
|
||||||
verbose_(f"{space}Skipping missing edited photo for {filename}")
|
verbose_(f"{space}Skipping missing edited photo for {filename}")
|
||||||
results.missing.append(str(pathlib.Path(dest_path) / filename))
|
results.missing.append(str(pathlib.Path(dest_path) / filename))
|
||||||
continue
|
continue
|
||||||
elif photo.intrash and (not photo.path_edited or use_photos_export):
|
elif (
|
||||||
|
photo.intrash
|
||||||
|
and (not photo.path_edited or use_photos_export)
|
||||||
|
and not preview_if_missing
|
||||||
|
):
|
||||||
# skip deleted files if they're missing or using use_photos_export
|
# skip deleted files if they're missing or using use_photos_export
|
||||||
# as AppleScript/PhotoKit cannot export deleted photos
|
# as AppleScript/PhotoKit cannot export deleted photos
|
||||||
space = " " if not verbose else ""
|
space = " " if not verbose else ""
|
||||||
@@ -2815,86 +2836,86 @@ def export_photo_with_template(
|
|||||||
while tries <= retry:
|
while tries <= retry:
|
||||||
tries += 1
|
tries += 1
|
||||||
error = 0
|
error = 0
|
||||||
try:
|
# try:
|
||||||
export_results = photo.export2(
|
export_results = photo.export2(
|
||||||
dest_path,
|
dest_path,
|
||||||
original_filename=filename,
|
original_filename=filename,
|
||||||
edited=edited,
|
edited=edited,
|
||||||
original=export_original,
|
original=export_original,
|
||||||
edited_filename=filename,
|
edited_filename=filename,
|
||||||
sidecar=sidecar_flags,
|
sidecar=sidecar_flags,
|
||||||
sidecar_drop_ext=sidecar_drop_ext,
|
sidecar_drop_ext=sidecar_drop_ext,
|
||||||
live_photo=export_live,
|
live_photo=export_live,
|
||||||
raw_photo=export_raw,
|
raw_photo=export_raw,
|
||||||
export_as_hardlink=export_as_hardlink,
|
export_as_hardlink=export_as_hardlink,
|
||||||
overwrite=overwrite,
|
overwrite=overwrite,
|
||||||
use_photos_export=use_photos_export,
|
use_photos_export=use_photos_export,
|
||||||
exiftool=exiftool,
|
exiftool=exiftool,
|
||||||
merge_exif_keywords=exiftool_merge_keywords,
|
merge_exif_keywords=exiftool_merge_keywords,
|
||||||
merge_exif_persons=exiftool_merge_persons,
|
merge_exif_persons=exiftool_merge_persons,
|
||||||
use_albums_as_keywords=album_keyword,
|
use_albums_as_keywords=album_keyword,
|
||||||
use_persons_as_keywords=person_keyword,
|
use_persons_as_keywords=person_keyword,
|
||||||
keyword_template=keyword_template,
|
keyword_template=keyword_template,
|
||||||
description_template=description_template,
|
description_template=description_template,
|
||||||
update=update,
|
update=update,
|
||||||
ignore_signature=ignore_signature,
|
ignore_signature=ignore_signature,
|
||||||
export_db=export_db,
|
export_db=export_db,
|
||||||
fileutil=fileutil,
|
fileutil=fileutil,
|
||||||
dry_run=dry_run,
|
dry_run=dry_run,
|
||||||
touch_file=touch_file,
|
touch_file=touch_file,
|
||||||
convert_to_jpeg=convert_to_jpeg,
|
convert_to_jpeg=convert_to_jpeg,
|
||||||
jpeg_quality=jpeg_quality,
|
jpeg_quality=jpeg_quality,
|
||||||
ignore_date_modified=ignore_date_modified,
|
ignore_date_modified=ignore_date_modified,
|
||||||
use_photokit=use_photokit,
|
use_photokit=use_photokit,
|
||||||
verbose=verbose_,
|
verbose=verbose_,
|
||||||
exiftool_flags=exiftool_option,
|
exiftool_flags=exiftool_option,
|
||||||
jpeg_ext=jpeg_ext,
|
jpeg_ext=jpeg_ext,
|
||||||
replace_keywords=replace_keywords,
|
replace_keywords=replace_keywords,
|
||||||
render_options=render_options,
|
render_options=render_options,
|
||||||
preview=export_preview,
|
preview=export_preview or (missing and preview_if_missing),
|
||||||
preview_suffix=preview_suffix,
|
preview_suffix=preview_suffix,
|
||||||
)
|
)
|
||||||
for warning_ in export_results.exiftool_warning:
|
for warning_ in export_results.exiftool_warning:
|
||||||
verbose_(f"exiftool warning for file {warning_[0]}: {warning_[1]}")
|
verbose_(f"exiftool warning for file {warning_[0]}: {warning_[1]}")
|
||||||
for error_ in export_results.exiftool_error:
|
for error_ in export_results.exiftool_error:
|
||||||
click.echo(
|
|
||||||
click.style(
|
|
||||||
f"exiftool error for file {error_[0]}: {error_[1]}",
|
|
||||||
fg=CLI_COLOR_ERROR,
|
|
||||||
),
|
|
||||||
err=True,
|
|
||||||
)
|
|
||||||
for error_ in export_results.error:
|
|
||||||
click.echo(
|
|
||||||
click.style(
|
|
||||||
f"Error exporting photo ({photo.uuid}: {photo.original_filename}) as {error_[0]}: {error_[1]}",
|
|
||||||
fg=CLI_COLOR_ERROR,
|
|
||||||
),
|
|
||||||
err=True,
|
|
||||||
)
|
|
||||||
error += 1
|
|
||||||
if not error or tries > retry:
|
|
||||||
results += export_results
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
click.echo(
|
|
||||||
"Retrying export for photo ({photo.uuid}: {photo.original_filename})"
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
click.echo(
|
click.echo(
|
||||||
click.style(
|
click.style(
|
||||||
f"Error exporting photo ({photo.uuid}: {photo.original_filename}) as {filename}: {e}",
|
f"exiftool error for file {error_[0]}: {error_[1]}",
|
||||||
fg=CLI_COLOR_ERROR,
|
fg=CLI_COLOR_ERROR,
|
||||||
),
|
),
|
||||||
err=True,
|
err=True,
|
||||||
)
|
)
|
||||||
if tries > retry:
|
for error_ in export_results.error:
|
||||||
results.error.append((str(pathlib.Path(dest) / filename), e))
|
click.echo(
|
||||||
break
|
click.style(
|
||||||
else:
|
f"Error exporting photo ({photo.uuid}: {photo.original_filename}) as {error_[0]}: {error_[1]}",
|
||||||
click.echo(
|
fg=CLI_COLOR_ERROR,
|
||||||
f"Retrying export for photo ({photo.uuid}: {photo.original_filename})"
|
),
|
||||||
)
|
err=True,
|
||||||
|
)
|
||||||
|
error += 1
|
||||||
|
if not error or tries > retry:
|
||||||
|
results += export_results
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
click.echo(
|
||||||
|
"Retrying export for photo ({photo.uuid}: {photo.original_filename})"
|
||||||
|
)
|
||||||
|
# except Exception as e:
|
||||||
|
# click.echo(
|
||||||
|
# click.style(
|
||||||
|
# f"Error exporting photo ({photo.uuid}: {photo.original_filename}) as {filename}: {e}",
|
||||||
|
# fg=CLI_COLOR_ERROR,
|
||||||
|
# ),
|
||||||
|
# err=True,
|
||||||
|
# )
|
||||||
|
# if tries > retry:
|
||||||
|
# results.error.append((str(pathlib.Path(dest) / filename), e))
|
||||||
|
# break
|
||||||
|
# else:
|
||||||
|
# click.echo(
|
||||||
|
# f"Retrying export for photo ({photo.uuid}: {photo.original_filename})"
|
||||||
|
# )
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
if update:
|
if update:
|
||||||
|
|||||||
@@ -770,18 +770,10 @@ def export2(
|
|||||||
# get path to source file and verify it's not None and is valid file
|
# get path to source file and verify it's not None and is valid file
|
||||||
# TODO: how to handle ismissing or not hasadjustments and edited=True cases?
|
# TODO: how to handle ismissing or not hasadjustments and edited=True cases?
|
||||||
export_src_dest = []
|
export_src_dest = []
|
||||||
if edited:
|
if edited and self.path_edited is not None:
|
||||||
if self.path_edited is not None:
|
export_src_dest.append((self.path_edited, dest_edited))
|
||||||
export_src_dest.append((self.path_edited, dest_edited))
|
elif not edited and self.path is not None:
|
||||||
else:
|
export_src_dest.append((self.path, dest_original))
|
||||||
raise FileNotFoundError(
|
|
||||||
f"Cannot export edited photo if path_edited is None"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
if self.path is not None:
|
|
||||||
export_src_dest.append((self.path, dest_original))
|
|
||||||
else:
|
|
||||||
raise FileNotFoundError("Cannot export photo if path is None")
|
|
||||||
|
|
||||||
for src, dest in export_src_dest:
|
for src, dest in export_src_dest:
|
||||||
if not pathlib.Path(src).is_file():
|
if not pathlib.Path(src).is_file():
|
||||||
@@ -907,7 +899,7 @@ def export2(
|
|||||||
all_results += results
|
all_results += results
|
||||||
|
|
||||||
# copy associated RAW image if requested
|
# copy associated RAW image if requested
|
||||||
if raw_photo and self.has_raw:
|
if raw_photo and self.has_raw and self.path_raw:
|
||||||
raw_path = pathlib.Path(self.path_raw)
|
raw_path = pathlib.Path(self.path_raw)
|
||||||
raw_ext = raw_path.suffix
|
raw_ext = raw_path.suffix
|
||||||
raw_name = dest.parent / f"{dest.stem}{raw_ext}"
|
raw_name = dest.parent / f"{dest.stem}{raw_ext}"
|
||||||
|
|||||||
@@ -787,7 +787,7 @@ def test_export_7(photosdb):
|
|||||||
|
|
||||||
def test_export_8(photosdb):
|
def test_export_8(photosdb):
|
||||||
# try to export missing file
|
# try to export missing file
|
||||||
# should raise exception
|
# should return empty list
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import tempfile
|
import tempfile
|
||||||
@@ -796,11 +796,7 @@ def test_export_8(photosdb):
|
|||||||
dest = tempdir.name
|
dest = tempdir.name
|
||||||
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
|
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
|
||||||
|
|
||||||
filename = photos[0].filename
|
assert photos[0].export(dest) == []
|
||||||
|
|
||||||
with pytest.raises(Exception) as e:
|
|
||||||
assert photos[0].export(dest)[0]
|
|
||||||
assert e.type == type(FileNotFoundError())
|
|
||||||
|
|
||||||
|
|
||||||
def test_export_9(photosdb):
|
def test_export_9(photosdb):
|
||||||
|
|||||||
@@ -866,17 +866,12 @@ def test_export_7(photosdb):
|
|||||||
|
|
||||||
def test_export_8(photosdb):
|
def test_export_8(photosdb):
|
||||||
# try to export missing file
|
# try to export missing file
|
||||||
# should raise exception
|
|
||||||
|
|
||||||
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
||||||
dest = tempdir.name
|
dest = tempdir.name
|
||||||
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
|
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
|
||||||
|
|
||||||
filename = photos[0].filename
|
assert photos[0].export(dest) == []
|
||||||
|
|
||||||
with pytest.raises(Exception) as e:
|
|
||||||
assert photos[0].export(dest)[0]
|
|
||||||
assert e.type == type(FileNotFoundError())
|
|
||||||
|
|
||||||
|
|
||||||
def test_export_9(photosdb):
|
def test_export_9(photosdb):
|
||||||
|
|||||||
@@ -777,6 +777,12 @@ UUID_DUPLICATES = [
|
|||||||
UUID_LOCATION = "D79B8D77-BFFC-460B-9312-034F2877D35B" # Pumkins2.jpg
|
UUID_LOCATION = "D79B8D77-BFFC-460B-9312-034F2877D35B" # Pumkins2.jpg
|
||||||
UUID_NO_LOCATION = "6191423D-8DB8-4D4C-92BE-9BBBA308AAC4" # Tulips.jpg"
|
UUID_NO_LOCATION = "6191423D-8DB8-4D4C-92BE-9BBBA308AAC4" # Tulips.jpg"
|
||||||
|
|
||||||
|
UUID_DICT_MISSING = {
|
||||||
|
"8E1D7BC9-9321-44F9-8CFB-4083F6B9232A": "IMG_2000.jpeg", # missing
|
||||||
|
"A1DD1F98-2ECD-431F-9AC9-5AFEFE2D3A5C": "Pumpkins4.jpeg", # missing
|
||||||
|
"D79B8D77-BFFC-460B-9312-034F2877D35B": "Pumkins2.jpg", # not missing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def modify_file(filename):
|
def modify_file(filename):
|
||||||
"""appends data to a file to modify it"""
|
"""appends data to a file to modify it"""
|
||||||
@@ -1305,6 +1311,40 @@ def test_export_preview_suffix():
|
|||||||
assert CLI_EXPORT_UUID_FILENAME_PREVIEW_TEMPLATE in files
|
assert CLI_EXPORT_UUID_FILENAME_PREVIEW_TEMPLATE in files
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_preview_if_missing():
|
||||||
|
"""test export with --preview_if_missing"""
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
import osxphotos
|
||||||
|
from osxphotos.cli import export
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
cwd = os.getcwd()
|
||||||
|
# pylint: disable=not-context-manager
|
||||||
|
with runner.isolated_filesystem():
|
||||||
|
uuid_options = []
|
||||||
|
for uuid in UUID_DICT_MISSING:
|
||||||
|
uuid_options.extend(["--uuid", uuid])
|
||||||
|
result = runner.invoke(
|
||||||
|
export,
|
||||||
|
[
|
||||||
|
os.path.join(cwd, CLI_PHOTOS_DB),
|
||||||
|
".",
|
||||||
|
"-V",
|
||||||
|
"--preview-if-missing",
|
||||||
|
"--preview-suffix",
|
||||||
|
"",
|
||||||
|
*uuid_options,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
assert result.exit_code == 0
|
||||||
|
files = glob.glob("*")
|
||||||
|
expected_files = list(UUID_DICT_MISSING.values())
|
||||||
|
assert sorted(files) == sorted(expected_files)
|
||||||
|
|
||||||
|
|
||||||
def test_export_as_hardlink():
|
def test_export_as_hardlink():
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
|
|||||||
@@ -240,7 +240,6 @@ def test_export_7(photosdb):
|
|||||||
|
|
||||||
def test_export_8(photosdb):
|
def test_export_8(photosdb):
|
||||||
# try to export missing file
|
# try to export missing file
|
||||||
# should raise exception
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import tempfile
|
import tempfile
|
||||||
@@ -249,12 +248,7 @@ def test_export_8(photosdb):
|
|||||||
dest = tempdir.name
|
dest = tempdir.name
|
||||||
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
|
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
|
||||||
|
|
||||||
filename = photos[0].filename
|
assert photos[0].export(dest) == []
|
||||||
expected_dest = os.path.join(dest, filename)
|
|
||||||
|
|
||||||
with pytest.raises(Exception) as e:
|
|
||||||
assert photos[0].export(dest)
|
|
||||||
assert e.type == type(FileNotFoundError())
|
|
||||||
|
|
||||||
|
|
||||||
def test_export_9(photosdb):
|
def test_export_9(photosdb):
|
||||||
|
|||||||
@@ -211,7 +211,6 @@ def test_export_7(photosdb):
|
|||||||
|
|
||||||
def test_export_8(photosdb):
|
def test_export_8(photosdb):
|
||||||
# try to export missing file
|
# try to export missing file
|
||||||
# should raise exception
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import tempfile
|
import tempfile
|
||||||
@@ -220,12 +219,7 @@ def test_export_8(photosdb):
|
|||||||
dest = tempdir.name
|
dest = tempdir.name
|
||||||
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
|
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
|
||||||
|
|
||||||
filename = photos[0].filename
|
assert photos[0].export(dest) == []
|
||||||
expected_dest = os.path.join(dest, filename)
|
|
||||||
|
|
||||||
with pytest.raises(Exception) as e:
|
|
||||||
assert photos[0].export(dest)[0]
|
|
||||||
assert e.type == type(FileNotFoundError())
|
|
||||||
|
|
||||||
|
|
||||||
def test_export_9(photosdb):
|
def test_export_9(photosdb):
|
||||||
|
|||||||
@@ -863,17 +863,12 @@ def test_export_7(photosdb):
|
|||||||
|
|
||||||
def test_export_8(photosdb):
|
def test_export_8(photosdb):
|
||||||
# try to export missing file
|
# try to export missing file
|
||||||
# should raise exception
|
|
||||||
|
|
||||||
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
||||||
dest = tempdir.name
|
dest = tempdir.name
|
||||||
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
|
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
|
||||||
|
|
||||||
filename = photos[0].filename
|
assert photos[0].export(dest) == []
|
||||||
|
|
||||||
with pytest.raises(Exception) as e:
|
|
||||||
assert photos[0].export(dest)[0]
|
|
||||||
assert e.type == type(FileNotFoundError())
|
|
||||||
|
|
||||||
|
|
||||||
def test_export_9(photosdb):
|
def test_export_9(photosdb):
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ def test_dd_to_dms():
|
|||||||
|
|
||||||
assert _dd_to_dms(-0.001) == (0, 0, -3.6)
|
assert _dd_to_dms(-0.001) == (0, 0, -3.6)
|
||||||
|
|
||||||
|
@pytest.mark.skip(reason="Fails on some machines")
|
||||||
def test_get_system_library_path():
|
def test_get_system_library_path():
|
||||||
import osxphotos
|
import osxphotos
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user