Changed default CLI behavior to export all photos
This commit is contained in:
@@ -855,12 +855,6 @@ def query(
|
||||
|
||||
@cli.command(cls=ExportCommand)
|
||||
@DB_OPTION
|
||||
# @click.option(
|
||||
# "--all",
|
||||
# is_flag=True,
|
||||
# help="Export all versions of photos including "
|
||||
# "edited photos, live photos, burst photos, and RAW photos.",
|
||||
# )
|
||||
@click.option("--verbose", "-V", is_flag=True, help="Print verbose output.")
|
||||
@query_options
|
||||
@click.option(
|
||||
@@ -878,29 +872,26 @@ def query(
|
||||
"(e.g. DEST/2019/12/20/photoname.jpg).",
|
||||
)
|
||||
@click.option(
|
||||
"--export-edited",
|
||||
"--skip-edited",
|
||||
is_flag=True,
|
||||
help="Also export edited version of photo if an edited version exists. "
|
||||
'Edited photo will be named in form of "photoname_edited.ext"',
|
||||
help="Do not export edited version of photo if an edited version exists.",
|
||||
)
|
||||
@click.option(
|
||||
"--export-bursts",
|
||||
"--skip-bursts",
|
||||
is_flag=True,
|
||||
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.",
|
||||
help="Do not export all associated burst images in the library if a photo is a burst photo. ",
|
||||
)
|
||||
@click.option(
|
||||
"--export-live",
|
||||
"--skip-live",
|
||||
is_flag=True,
|
||||
help="If a photo is a live photo export the associated live video component."
|
||||
" Live video will have same name as photo but with .mov extension. ",
|
||||
help="Do not export the associated live video component of a live photo.",
|
||||
)
|
||||
@click.option(
|
||||
"--export-raw",
|
||||
"--skip-raw",
|
||||
is_flag=True,
|
||||
help="If a photo was imported in RAW format with associated jpeg, also export the "
|
||||
"RAW photo in addition to the jpeg. (By default, Photos treats the jpeg as the "
|
||||
"original image.)",
|
||||
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(
|
||||
"--original-name",
|
||||
@@ -986,10 +977,10 @@ def export(
|
||||
verbose,
|
||||
overwrite,
|
||||
export_by_date,
|
||||
export_edited,
|
||||
export_bursts,
|
||||
export_live,
|
||||
export_raw,
|
||||
skip_edited,
|
||||
skip_bursts,
|
||||
skip_live,
|
||||
skip_raw,
|
||||
original_name,
|
||||
sidecar,
|
||||
only_photos,
|
||||
@@ -1027,6 +1018,10 @@ def export(
|
||||
if more than one option is provided, they are treated as "AND"
|
||||
(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.
|
||||
See --skip-edited, --skip-live, --skip-bursts, and --skip-raw options
|
||||
to modify this behavior.
|
||||
"""
|
||||
|
||||
if not os.path.isdir(dest):
|
||||
@@ -1055,6 +1050,12 @@ def export(
|
||||
click.echo(cli.commands["export"].get_help(ctx), err=True)
|
||||
return
|
||||
|
||||
# initialize export flags
|
||||
# by default, will export all versions of photos unless skip flag is set
|
||||
(export_edited, export_bursts, export_live, export_raw) = [
|
||||
not x for x in [skip_edited, skip_bursts, skip_live, skip_raw]
|
||||
]
|
||||
|
||||
# verify exiftool installed an in path
|
||||
if exiftool:
|
||||
try:
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.27.7"
|
||||
__version__ = "0.28.0"
|
||||
|
||||
@@ -718,7 +718,7 @@ class PhotoInfo:
|
||||
# Photo's often converts .JPG to .jpeg
|
||||
suffixes = sorted([x.lower() for x in [dest.suffix, actual_suffix]])
|
||||
if dest.suffix != actual_suffix and suffixes != [".jpeg", ".jpg"]:
|
||||
logging.warning(
|
||||
logging.debug(
|
||||
f"Invalid destination suffix: {dest.suffix}, should be {actual_suffix}"
|
||||
)
|
||||
|
||||
|
||||
@@ -206,6 +206,25 @@ def test_export():
|
||||
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), ".", "--original-name", "-V"]
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
files = glob.glob("*")
|
||||
assert sorted(files) == sorted(CLI_EXPORT_FILENAMES)
|
||||
|
||||
|
||||
def test_export_skip_edited():
|
||||
import glob
|
||||
import os
|
||||
import os.path
|
||||
import osxphotos
|
||||
from osxphotos.__main__ import export
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
# pylint: disable=not-context-manager
|
||||
@@ -215,14 +234,14 @@ def test_export():
|
||||
[
|
||||
os.path.join(cwd, CLI_PHOTOS_DB),
|
||||
".",
|
||||
"--skip-edited",
|
||||
"--original-name",
|
||||
"--export-edited",
|
||||
"-V",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
files = glob.glob("*")
|
||||
assert sorted(files) == sorted(CLI_EXPORT_FILENAMES)
|
||||
assert "St James Park_edited.jpeg" not in files
|
||||
|
||||
|
||||
def test_query_date():
|
||||
@@ -290,6 +309,25 @@ def test_export_live():
|
||||
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, LIVE_PHOTOS_DB), ".", "--live", "--original-name", "-V"],
|
||||
)
|
||||
files = glob.glob("*")
|
||||
assert sorted(files) == sorted(CLI_EXPORT_LIVE_ORIGINAL)
|
||||
|
||||
|
||||
def test_export_skip_live():
|
||||
import glob
|
||||
import os
|
||||
import os.path
|
||||
import osxphotos
|
||||
from osxphotos.__main__ import export
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
# pylint: disable=not-context-manager
|
||||
@@ -299,14 +337,13 @@ def test_export_live():
|
||||
[
|
||||
os.path.join(cwd, LIVE_PHOTOS_DB),
|
||||
".",
|
||||
"--live",
|
||||
"--skip-live",
|
||||
"--original-name",
|
||||
"--export-live",
|
||||
"-V",
|
||||
],
|
||||
)
|
||||
files = glob.glob("*")
|
||||
assert sorted(files) == sorted(CLI_EXPORT_LIVE_ORIGINAL)
|
||||
assert "img_0728.mov" not in [f.lower() for f in files]
|
||||
|
||||
|
||||
def test_export_raw():
|
||||
@@ -320,11 +357,33 @@ def test_export_raw():
|
||||
cwd = os.getcwd()
|
||||
# pylint: disable=not-context-manager
|
||||
with runner.isolated_filesystem():
|
||||
result = runner.invoke(export, [os.path.join(cwd, RAW_PHOTOS_DB), ".", "-V"])
|
||||
result = runner.invoke(
|
||||
export, [os.path.join(cwd, RAW_PHOTOS_DB), ".", "--skip-edited", "-V"]
|
||||
)
|
||||
files = glob.glob("*")
|
||||
assert sorted(files) == sorted(CLI_EXPORT_RAW)
|
||||
|
||||
|
||||
# TODO: Update this once RAW db is added
|
||||
# def test_skip_raw():
|
||||
# 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, RAW_PHOTOS_DB), ".", "--skip-raw", "-V"]
|
||||
# )
|
||||
# files = glob.glob("*")
|
||||
# for rawname in CLI_EXPORT_RAW:
|
||||
# assert rawname.lower() not in [f.lower() for f in files]
|
||||
|
||||
|
||||
def test_export_raw_original():
|
||||
import glob
|
||||
import os
|
||||
@@ -337,7 +396,14 @@ def test_export_raw_original():
|
||||
# pylint: disable=not-context-manager
|
||||
with runner.isolated_filesystem():
|
||||
result = runner.invoke(
|
||||
export, [os.path.join(cwd, RAW_PHOTOS_DB), ".", "--original-name", "-V"]
|
||||
export,
|
||||
[
|
||||
os.path.join(cwd, RAW_PHOTOS_DB),
|
||||
".",
|
||||
"--skip-edited",
|
||||
"--original-name",
|
||||
"-V",
|
||||
],
|
||||
)
|
||||
files = glob.glob("*")
|
||||
assert sorted(files) == sorted(CLI_EXPORT_RAW_ORIGINAL)
|
||||
@@ -354,9 +420,7 @@ def test_export_raw_edited():
|
||||
cwd = os.getcwd()
|
||||
# pylint: disable=not-context-manager
|
||||
with runner.isolated_filesystem():
|
||||
result = runner.invoke(
|
||||
export, [os.path.join(cwd, RAW_PHOTOS_DB), ".", "--export-edited", "-V"]
|
||||
)
|
||||
result = runner.invoke(export, [os.path.join(cwd, RAW_PHOTOS_DB), ".", "-V"])
|
||||
files = glob.glob("*")
|
||||
assert sorted(files) == sorted(CLI_EXPORT_RAW_EDITED)
|
||||
|
||||
@@ -373,14 +437,7 @@ def test_export_raw_edited_original():
|
||||
# pylint: disable=not-context-manager
|
||||
with runner.isolated_filesystem():
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
os.path.join(cwd, RAW_PHOTOS_DB),
|
||||
".",
|
||||
"--export-edited",
|
||||
"--original-name",
|
||||
"-V",
|
||||
],
|
||||
export, [os.path.join(cwd, RAW_PHOTOS_DB), ".", "--original-name", "-V"]
|
||||
)
|
||||
files = glob.glob("*")
|
||||
assert sorted(files) == sorted(CLI_EXPORT_RAW_EDITED_ORIGINAL)
|
||||
|
||||
@@ -104,7 +104,7 @@ def test_export_edited_default():
|
||||
assert pathlib.Path(got_dest).name == FILENAME_DICT["current_edited"]
|
||||
|
||||
|
||||
def test_export_edited_wrong_suffix(caplog):
|
||||
def test_export_edited_wrong_suffix():
|
||||
# export edited file with name provided but wrong suffix
|
||||
# should produce a warning via logging.warning
|
||||
import os
|
||||
@@ -126,7 +126,6 @@ def test_export_edited_wrong_suffix(caplog):
|
||||
expected_dest = os.path.join(dest, filename)
|
||||
|
||||
got_dest = photos[0].export(dest, filename, edited=True)[0]
|
||||
assert "Invalid destination suffix" in caplog.text
|
||||
# assert "Invalid destination suffix" in caplog.text
|
||||
assert got_dest == expected_dest
|
||||
assert pathlib.Path(got_dest).name == filename
|
||||
|
||||
|
||||
Reference in New Issue
Block a user