Added --missing to export, see issue #277
This commit is contained in:
@@ -227,6 +227,9 @@ Options:
|
||||
--no-comment Search for photos with no comments.
|
||||
--has-likes Search for photos that have likes.
|
||||
--no-likes Search for photos with no likes.
|
||||
--missing Export only photos missing from the Photos
|
||||
library; must be used with --download-
|
||||
missing.
|
||||
--deleted Include photos from the 'Recently Deleted'
|
||||
folder.
|
||||
--deleted-only Include only photos from the 'Recently
|
||||
@@ -234,7 +237,8 @@ Options:
|
||||
--update Only export new or updated files. See notes
|
||||
below on export and --update.
|
||||
--dry-run Dry run (test) the export but don't actually
|
||||
export any files; most useful with --verbose
|
||||
export any files; most useful with
|
||||
--verbose.
|
||||
--export-as-hardlink Hardlink files instead of copying them.
|
||||
Cannot be used with --exiftool which creates
|
||||
copies of the files with embedded EXIF data.
|
||||
|
||||
@@ -98,7 +98,7 @@ class DateTimeISO8601(click.ParamType):
|
||||
def convert(self, value, param, ctx):
|
||||
try:
|
||||
return datetime.datetime.fromisoformat(value)
|
||||
except:
|
||||
except Exception:
|
||||
self.fail(
|
||||
f"Invalid value for --{param.name}: invalid datetime format {value}. "
|
||||
"Valid format: YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]]"
|
||||
@@ -651,7 +651,7 @@ def debug_dump(ctx, cli_obj, db, photos_library, dump, uuid, verbose_):
|
||||
val = getattr(photosdb, attr)
|
||||
print(f"{attr}:")
|
||||
pprint.pprint(val)
|
||||
except:
|
||||
except Exception:
|
||||
print(f"Did not find attribute {attr} in PhotosDB")
|
||||
|
||||
|
||||
@@ -846,12 +846,12 @@ def places(ctx, cli_obj, db, json_, photos_library):
|
||||
if photo.place:
|
||||
try:
|
||||
place_names[photo.place.name] += 1
|
||||
except:
|
||||
except Exception:
|
||||
place_names[photo.place.name] = 1
|
||||
else:
|
||||
try:
|
||||
place_names[_UNKNOWN_PLACE] += 1
|
||||
except:
|
||||
except Exception:
|
||||
place_names[_UNKNOWN_PLACE] = 1
|
||||
|
||||
# sort by place count
|
||||
@@ -1199,6 +1199,11 @@ def query(
|
||||
@DB_OPTION
|
||||
@click.option("--verbose", "-V", "verbose_", is_flag=True, help="Print verbose output.")
|
||||
@query_options
|
||||
@click.option(
|
||||
"--missing",
|
||||
is_flag=True,
|
||||
help="Export only photos missing from the Photos library; must be used with --download-missing.",
|
||||
)
|
||||
@deleted_options
|
||||
@click.option(
|
||||
"--update",
|
||||
@@ -1208,7 +1213,7 @@ def query(
|
||||
@click.option(
|
||||
"--dry-run",
|
||||
is_flag=True,
|
||||
help="Dry run (test) the export but don't actually export any files; most useful with --verbose",
|
||||
help="Dry run (test) the export but don't actually export any files; most useful with --verbose.",
|
||||
)
|
||||
@click.option(
|
||||
"--export-as-hardlink",
|
||||
@@ -1451,6 +1456,7 @@ def export(
|
||||
from_date,
|
||||
to_date,
|
||||
verbose_,
|
||||
missing,
|
||||
update,
|
||||
dry_run,
|
||||
export_as_hardlink,
|
||||
@@ -1567,6 +1573,20 @@ def export(
|
||||
click.echo(cli.commands["export"].get_help(ctx), err=True)
|
||||
return
|
||||
|
||||
if export_as_hardlink and download_missing:
|
||||
click.echo(
|
||||
"Incompatible export options: --export-as-hardlink is not compatible with --download-missing",
|
||||
err=True,
|
||||
)
|
||||
raise click.Abort()
|
||||
|
||||
if missing and not download_missing:
|
||||
click.echo(
|
||||
"Incompatible export options: --missing must be used with --download-missing",
|
||||
err=True,
|
||||
)
|
||||
raise click.Abort()
|
||||
|
||||
if use_photokit and not check_photokit_authorization():
|
||||
click.echo(
|
||||
"Requesting access to use your Photos library. Click 'OK' on the dialog box to grant access."
|
||||
@@ -1674,7 +1694,7 @@ def export(
|
||||
not_favorite=not_favorite,
|
||||
hidden=hidden,
|
||||
not_hidden=not_hidden,
|
||||
missing=None, # missing -- won't export these but will warn user
|
||||
missing=missing,
|
||||
not_missing=None,
|
||||
shared=shared,
|
||||
not_shared=not_shared,
|
||||
@@ -2575,7 +2595,7 @@ def export_photo(
|
||||
verbose(f"Skipped up to date file {skipped}")
|
||||
for touched in export_results.touched:
|
||||
verbose(f"Touched date on file {touched}")
|
||||
except:
|
||||
except Exception:
|
||||
click.echo(
|
||||
f"Error exporting photo {photo.original_filename} ({photo.filename}) as {original_filename}",
|
||||
err=True,
|
||||
@@ -2603,7 +2623,7 @@ def export_photo(
|
||||
f"{edited_filename.stem}{edited_suffix}{edited_ext}"
|
||||
)
|
||||
verbose(
|
||||
f"Exporting edited version of {filename} as {edited_filename}"
|
||||
f"Exporting edited version of {photo.original_filename} ({photo.filename}) as {edited_filename}"
|
||||
)
|
||||
try:
|
||||
export_results_edited = photo.export2(
|
||||
@@ -2666,7 +2686,7 @@ def export_photo(
|
||||
verbose(f"Skipped up to date file {skipped}")
|
||||
for touched in export_results_edited.touched:
|
||||
verbose(f"Touched date on file {touched}")
|
||||
except:
|
||||
except Exception:
|
||||
click.echo(
|
||||
f"Error exporting photo {filename} as {edited_filename}",
|
||||
err=True,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.37.1"
|
||||
__version__ = "0.37.2"
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ PLACES_PHOTOS_DB_13 = "tests/Test-Places-High-Sierra-10.13.6.photoslibrary"
|
||||
PHOTOS_DB_15_4 = "tests/Test-10.15.4.photoslibrary"
|
||||
PHOTOS_DB_15_5 = "tests/Test-10.15.5.photoslibrary"
|
||||
PHOTOS_DB_15_6 = "tests/Test-10.15.6.photoslibrary"
|
||||
PHOTOS_DB_15_7 = "tests/Test-10.15.7.photoslibrary"
|
||||
PHOTOS_DB_TOUCH = PHOTOS_DB_15_6
|
||||
PHOTOS_DB_14_6 = "tests/Test-10.14.6.photoslibrary"
|
||||
|
||||
@@ -3804,3 +3805,75 @@ def test_export_report_not_a_file():
|
||||
assert result.exit_code != 0
|
||||
assert "Aborted!" in result.output
|
||||
|
||||
|
||||
def test_export_as_hardlink_download_missing():
|
||||
""" test export with incompatible export options """
|
||||
import glob
|
||||
import os
|
||||
import os.path
|
||||
import osxphotos
|
||||
from osxphotos.__main__ import export
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
# pylint: disable=not-context-manager
|
||||
with runner.isolated_filesystem():
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
os.path.join(cwd, CLI_PHOTOS_DB),
|
||||
".",
|
||||
"-V",
|
||||
"--download-missing",
|
||||
"--export-as-hardlink",
|
||||
".",
|
||||
],
|
||||
)
|
||||
assert result.exit_code != 0
|
||||
assert "Aborted!" in result.output
|
||||
|
||||
|
||||
def test_export_missing():
|
||||
""" test export with --missing """
|
||||
import glob
|
||||
import os
|
||||
import os.path
|
||||
import osxphotos
|
||||
from osxphotos.__main__ import export
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
# pylint: disable=not-context-manager
|
||||
with runner.isolated_filesystem():
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
".",
|
||||
"-V",
|
||||
"--missing",
|
||||
"--download-missing",
|
||||
".",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "Exporting 2 photos" in result.output
|
||||
|
||||
|
||||
def test_export_missing_not_download_missing():
|
||||
""" test export with incompatible export options """
|
||||
import glob
|
||||
import os
|
||||
import os.path
|
||||
import osxphotos
|
||||
from osxphotos.__main__ import export
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
# pylint: disable=not-context-manager
|
||||
with runner.isolated_filesystem():
|
||||
result = runner.invoke(
|
||||
export, [os.path.join(cwd, CLI_PHOTOS_DB), ".", "-V", "--missing", "."]
|
||||
)
|
||||
assert result.exit_code != 0
|
||||
assert "Aborted!" in result.output
|
||||
|
||||
Reference in New Issue
Block a user