Added --uuid-from-file to CLI
This commit is contained in:
parent
002fce8e93
commit
840e9937be
@ -138,6 +138,9 @@ Options:
|
||||
searches top level folders (e.g. does not
|
||||
look at subfolders)
|
||||
--uuid UUID Search for photos with UUID(s).
|
||||
--uuid-from-file FILE Search for photos with UUID(s) loaded from
|
||||
FILE. Format is a single UUID per line.
|
||||
Lines preceeded with # are ignored.
|
||||
--title TITLE Search for TITLE in title of photo.
|
||||
--no-title Search for photos with no title.
|
||||
--description DESC Search for DESC in description of photo.
|
||||
|
||||
@ -298,6 +298,15 @@ def query_options(f):
|
||||
multiple=True,
|
||||
help="Search for photos with UUID(s).",
|
||||
),
|
||||
o(
|
||||
"--uuid-from-file",
|
||||
metavar="FILE",
|
||||
default=None,
|
||||
multiple=False,
|
||||
help="Search for photos with UUID(s) loaded from FILE. "
|
||||
"Format is a single UUID per line. Lines preceeded with # are ignored.",
|
||||
type=click.Path(exists=True)
|
||||
),
|
||||
o(
|
||||
"--title",
|
||||
metavar="TITLE",
|
||||
@ -891,6 +900,7 @@ def query(
|
||||
album,
|
||||
folder,
|
||||
uuid,
|
||||
uuid_from_file,
|
||||
title,
|
||||
no_title,
|
||||
description,
|
||||
@ -954,6 +964,7 @@ def query(
|
||||
album,
|
||||
folder,
|
||||
uuid,
|
||||
uuid_from_file,
|
||||
edited,
|
||||
external_edit,
|
||||
uti,
|
||||
@ -998,6 +1009,12 @@ def query(
|
||||
if only_photos:
|
||||
ismovie = False
|
||||
|
||||
# load UUIDs if necessary and append to any uuids passed with --uuid
|
||||
if uuid_from_file:
|
||||
uuid_list = list(uuid) # Click option is a tuple
|
||||
uuid_list.extend(load_uuid_from_file(uuid_from_file))
|
||||
uuid = tuple(uuid_list)
|
||||
|
||||
# below needed for to make CliRunner work for testing
|
||||
cli_db = cli_obj.db if cli_obj is not None else None
|
||||
db = get_photos_db(*photos_library, db, cli_db)
|
||||
@ -1247,6 +1264,7 @@ def export(
|
||||
album,
|
||||
folder,
|
||||
uuid,
|
||||
uuid_from_file,
|
||||
title,
|
||||
no_title,
|
||||
description,
|
||||
@ -1329,7 +1347,7 @@ def export(
|
||||
VERBOSE = True if verbose_ else False
|
||||
|
||||
if not os.path.isdir(dest):
|
||||
sys.exit("DEST must be valid path")
|
||||
sys.exit(f"DEST {dest} must be valid path")
|
||||
|
||||
# sanity check input args
|
||||
exclusive = [
|
||||
@ -1381,6 +1399,12 @@ def export(
|
||||
if only_photos:
|
||||
ismovie = False
|
||||
|
||||
# load UUIDs if necessary and append to any uuids passed with --uuid
|
||||
if uuid_from_file:
|
||||
uuid_list = list(uuid) # Click option is a tuple
|
||||
uuid_list.extend(load_uuid_from_file(uuid_from_file))
|
||||
uuid = tuple(uuid_list)
|
||||
|
||||
# below needed for to make CliRunner work for testing
|
||||
cli_db = cli_obj.db if cli_obj is not None else None
|
||||
db = get_photos_db(*photos_library, db, cli_db)
|
||||
@ -2091,6 +2115,12 @@ def export_photo(
|
||||
)
|
||||
return ExportResults([], [], [], [], [])
|
||||
|
||||
results_exported = []
|
||||
results_new = []
|
||||
results_updated = []
|
||||
results_skipped = []
|
||||
results_exif_updated = []
|
||||
|
||||
filenames = get_filenames_from_template(photo, filename_template, original_name)
|
||||
for filename in filenames:
|
||||
verbose(f"Exporting {photo.filename} as {filename}")
|
||||
@ -2113,11 +2143,6 @@ def export_photo(
|
||||
)
|
||||
|
||||
# export the photo to each path in dest_paths
|
||||
results_exported = []
|
||||
results_new = []
|
||||
results_updated = []
|
||||
results_skipped = []
|
||||
results_exif_updated = []
|
||||
for dest_path in dest_paths:
|
||||
export_results = photo.export2(
|
||||
dest_path,
|
||||
@ -2338,6 +2363,31 @@ def find_files_in_branch(pathname, filename):
|
||||
|
||||
return files
|
||||
|
||||
def load_uuid_from_file(filename):
|
||||
""" Load UUIDs from file. Does not validate UUIDs.
|
||||
Format is 1 UUID per line, any line beginning with # is ignored.
|
||||
Whitespace is stripped.
|
||||
|
||||
Arguments:
|
||||
filename: file name of the file containing UUIDs
|
||||
|
||||
Returns:
|
||||
list of UUIDs or empty list of no UUIDs in file
|
||||
|
||||
Raises:
|
||||
FileNotFoundError if file does not exist
|
||||
"""
|
||||
|
||||
if not pathlib.Path(filename).is_file():
|
||||
raise FileNotFoundError(f"Could not find file {filename}")
|
||||
|
||||
uuid = []
|
||||
with open(filename, "r") as uuid_file:
|
||||
for line in uuid_file:
|
||||
line = line.strip()
|
||||
if len(line) and line[0] != "#":
|
||||
uuid.append(line)
|
||||
return uuid
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli() # pylint: disable=no-value-for-parameter
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.31.0"
|
||||
__version__ = "0.31.1"
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
""" Test the command line interface (CLI) """
|
||||
|
||||
import os
|
||||
|
||||
import pytest
|
||||
@ -14,6 +16,8 @@ PHOTOS_DB_15_4 = "tests/Test-10.15.4.photoslibrary"
|
||||
PHOTOS_DB_15_5 = "tests/Test-10.15.5.photoslibrary"
|
||||
PHOTOS_DB_14_6 = "tests/Test-10.14.6.photoslibrary"
|
||||
|
||||
UUID_FILE = "tests/uuid_from_file.txt"
|
||||
|
||||
CLI_OUTPUT_NO_SUBCOMMAND = [
|
||||
"Options:",
|
||||
"--db <Photos database path> Specify Photos database path. Path to Photos",
|
||||
@ -295,6 +299,23 @@ ALBUMS_JSON = {
|
||||
|
||||
PERSONS_JSON = {"persons": {"Katie": 3, "Suzy": 2, "_UNKNOWN_": 1, "Maria": 2}}
|
||||
|
||||
UUID_EXPECTED_FROM_FILE = [
|
||||
"E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51",
|
||||
"6191423D-8DB8-4D4C-92BE-9BBBA308AAC4",
|
||||
"A92D9C26-3A50-4197-9388-CB5F7DB9FA91",
|
||||
]
|
||||
|
||||
UUID_NOT_FROM_FILE = "D79B8D77-BFFC-460B-9312-034F2877D35B"
|
||||
|
||||
CLI_EXPORT_UUID_FROM_FILE_FILENAMES = [
|
||||
"IMG_1994.JPG",
|
||||
"IMG_1994.cr2",
|
||||
"Tulips.jpg",
|
||||
"Tulips_edited.jpeg",
|
||||
"wedding.jpg",
|
||||
"wedding_edited.jpeg",
|
||||
]
|
||||
|
||||
# determine if exiftool installed so exiftool tests can be skipped
|
||||
try:
|
||||
exiftool = get_exiftool_path()
|
||||
@ -390,6 +411,72 @@ def test_query_uuid():
|
||||
assert json_expected[key_] in json_got[key_]
|
||||
|
||||
|
||||
def test_query_uuid_from_file_1():
|
||||
""" Test query with --uuid-from-file """
|
||||
import json
|
||||
import os
|
||||
import os.path
|
||||
import osxphotos
|
||||
from osxphotos.__main__ import query
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
result = runner.invoke(
|
||||
query,
|
||||
[
|
||||
"--json",
|
||||
"--db",
|
||||
os.path.join(cwd, PHOTOS_DB_15_5),
|
||||
"--uuid-from-file",
|
||||
UUID_FILE,
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
# build list of uuids we got from the output JSON
|
||||
json_got = json.loads(result.output)
|
||||
uuid_got = []
|
||||
for photo in json_got:
|
||||
uuid_got.append(photo["uuid"])
|
||||
|
||||
assert sorted(UUID_EXPECTED_FROM_FILE) == sorted(uuid_got)
|
||||
|
||||
|
||||
def test_query_uuid_from_file_2():
|
||||
""" Test query with --uuid-from-file and --uuid """
|
||||
import json
|
||||
import os
|
||||
import os.path
|
||||
import osxphotos
|
||||
from osxphotos.__main__ import query
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
result = runner.invoke(
|
||||
query,
|
||||
[
|
||||
"--json",
|
||||
"--db",
|
||||
os.path.join(cwd, PHOTOS_DB_15_5),
|
||||
"--uuid-from-file",
|
||||
UUID_FILE,
|
||||
"--uuid",
|
||||
UUID_NOT_FROM_FILE,
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
# build list of uuids we got from the output JSON
|
||||
json_got = json.loads(result.output)
|
||||
uuid_got = []
|
||||
for photo in json_got:
|
||||
uuid_got.append(photo["uuid"])
|
||||
|
||||
uuid_expected = UUID_EXPECTED_FROM_FILE.copy()
|
||||
uuid_expected.append(UUID_NOT_FROM_FILE)
|
||||
assert sorted(uuid_expected) == sorted(uuid_got)
|
||||
|
||||
|
||||
def test_export():
|
||||
import glob
|
||||
import os
|
||||
@ -407,6 +494,33 @@ def test_export():
|
||||
assert sorted(files) == sorted(CLI_EXPORT_FILENAMES)
|
||||
|
||||
|
||||
def test_export_uuid_from_file():
|
||||
""" Test export with --uuid-from-file """
|
||||
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_5),
|
||||
".",
|
||||
"-V",
|
||||
"--uuid-from-file",
|
||||
os.path.join(cwd, UUID_FILE),
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
files = glob.glob("*")
|
||||
assert sorted(files) == sorted(CLI_EXPORT_UUID_FROM_FILE_FILENAMES)
|
||||
|
||||
|
||||
def test_export_as_hardlink():
|
||||
import glob
|
||||
import os
|
||||
@ -2468,7 +2582,7 @@ def test_albums():
|
||||
|
||||
|
||||
def test_persons():
|
||||
"""Test osxphotos albums """
|
||||
"""Test osxphotos persons """
|
||||
import json
|
||||
import osxphotos
|
||||
import os
|
||||
|
||||
29
tests/test_cli_utils.py
Normal file
29
tests/test_cli_utils.py
Normal file
@ -0,0 +1,29 @@
|
||||
""" Test utility functions in __main__.py """
|
||||
|
||||
import pytest
|
||||
|
||||
UUID_FILE = "tests/uuid_from_file.txt"
|
||||
MISSING_UUID_FILE = "tests/uuid_not_found.txt"
|
||||
|
||||
UUID_EXPECTED_FROM_FILE = [
|
||||
"E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51",
|
||||
"6191423D-8DB8-4D4C-92BE-9BBBA308AAC4",
|
||||
"A92D9C26-3A50-4197-9388-CB5F7DB9FA91",
|
||||
]
|
||||
|
||||
|
||||
def test_load_uuid_from_file():
|
||||
"""Test load_uuid_from_file function """
|
||||
from osxphotos.__main__ import load_uuid_from_file
|
||||
|
||||
uuid_got = load_uuid_from_file(UUID_FILE)
|
||||
assert uuid_got == UUID_EXPECTED_FROM_FILE
|
||||
|
||||
|
||||
def test_load_uuid_from_file_filenotfound():
|
||||
"""Test load_uuid_from_file function raises error if file not found"""
|
||||
from osxphotos.__main__ import load_uuid_from_file
|
||||
|
||||
with pytest.raises(FileNotFoundError) as err:
|
||||
uuid_got = load_uuid_from_file(MISSING_UUID_FILE)
|
||||
assert "Could not find" in str(err.value)
|
||||
7
tests/uuid_from_file.txt
Normal file
7
tests/uuid_from_file.txt
Normal file
@ -0,0 +1,7 @@
|
||||
# Test file for load_uuid_from_file
|
||||
E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51
|
||||
6191423D-8DB8-4D4C-92BE-9BBBA308AAC4
|
||||
|
||||
# D79B8D77-BFFC-460B-9312-034F2877D35B
|
||||
A92D9C26-3A50-4197-9388-CB5F7DB9FA91
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user