Added --has-comment/--has-likes to CLI, issue #240
This commit is contained in:
@@ -221,6 +221,10 @@ Options:
|
||||
2000-01-12T12:00:00,
|
||||
2001-01-12T12:00:00-07:00, or 2000-12-31
|
||||
(ISO 8601).
|
||||
--has-comment Search for photos that have comments.
|
||||
--no-comment Search for photos with no comments.
|
||||
--has-likes Search for photos that have likes.
|
||||
--no-likes Search for photos with no likes.
|
||||
--deleted Include photos from the 'Recently Deleted'
|
||||
folder.
|
||||
--deleted-only Include only photos from the 'Recently
|
||||
@@ -542,6 +546,7 @@ Substitution Description
|
||||
(Photos 5 only)
|
||||
{label_normalized} All lower case version of 'label' (Photos 5 only)
|
||||
{comment} Comment(s) on shared Photos; format is 'Person name:
|
||||
comment text' (Photos 5 only)
|
||||
```
|
||||
|
||||
Example: export all photos to ~/Desktop/export group in folders by date created
|
||||
|
||||
@@ -489,6 +489,10 @@ def query_options(f):
|
||||
help="Search by end item date, e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601).",
|
||||
type=DateTimeISO8601(),
|
||||
),
|
||||
o("--has-comment", is_flag=True, help="Search for photos that have comments."),
|
||||
o("--no-comment", is_flag=True, help="Search for photos with no comments."),
|
||||
o("--has-likes", is_flag=True, help="Search for photos that have likes."),
|
||||
o("--no-likes", is_flag=True, help="Search for photos with no likes."),
|
||||
]
|
||||
for o in options[::-1]:
|
||||
f = o(f)
|
||||
@@ -529,7 +533,7 @@ def debug_dump(ctx, cli_obj, db, photos_library, dump, uuid, verbose_):
|
||||
|
||||
global VERBOSE
|
||||
VERBOSE = bool(verbose_)
|
||||
|
||||
|
||||
db = get_photos_db(*photos_library, db, cli_obj.db)
|
||||
if db is None:
|
||||
click.echo(cli.commands["debug-dump"].get_help(ctx), err=True)
|
||||
@@ -982,6 +986,10 @@ def query(
|
||||
label,
|
||||
deleted,
|
||||
deleted_only,
|
||||
has_comment,
|
||||
no_comment,
|
||||
has_likes,
|
||||
no_likes,
|
||||
):
|
||||
""" Query the Photos database using 1 or more search options;
|
||||
if more than one option is provided, they are treated as "AND"
|
||||
@@ -1026,6 +1034,8 @@ def query(
|
||||
(any(place), no_place),
|
||||
(deleted, deleted_only),
|
||||
(shared, not_shared),
|
||||
(has_comment, no_comment),
|
||||
(has_likes, no_likes),
|
||||
]
|
||||
# print help if no non-exclusive term or a double exclusive term is given
|
||||
if any(all(bb) for bb in exclusive) or not any(
|
||||
@@ -1112,6 +1122,10 @@ def query(
|
||||
label=label,
|
||||
deleted=deleted,
|
||||
deleted_only=deleted_only,
|
||||
has_comment=has_comment,
|
||||
no_comment=no_comment,
|
||||
has_likes=has_likes,
|
||||
no_likes=no_likes,
|
||||
)
|
||||
|
||||
# below needed for to make CliRunner work for testing
|
||||
@@ -1395,6 +1409,10 @@ def export(
|
||||
edited_suffix,
|
||||
place,
|
||||
no_place,
|
||||
has_comment,
|
||||
no_comment,
|
||||
has_likes,
|
||||
no_likes,
|
||||
no_extended_attributes,
|
||||
label,
|
||||
deleted,
|
||||
@@ -1442,6 +1460,8 @@ def export(
|
||||
(skip_edited, skip_original_if_edited),
|
||||
(export_as_hardlink, convert_to_jpeg),
|
||||
(shared, not_shared),
|
||||
(has_comment, no_comment),
|
||||
(has_likes, no_likes),
|
||||
]
|
||||
if any(all(bb) for bb in exclusive):
|
||||
click.echo("Incompatible export options", err=True)
|
||||
@@ -1580,6 +1600,10 @@ def export(
|
||||
label=label,
|
||||
deleted=deleted,
|
||||
deleted_only=deleted_only,
|
||||
has_comment=has_comment,
|
||||
no_comment=no_comment,
|
||||
has_likes=has_likes,
|
||||
no_likes=no_likes,
|
||||
)
|
||||
|
||||
if photos:
|
||||
@@ -1899,6 +1923,10 @@ def _query(
|
||||
label=None,
|
||||
deleted=False,
|
||||
deleted_only=False,
|
||||
has_comment=False,
|
||||
no_comment=False,
|
||||
has_likes=False,
|
||||
no_likes=False,
|
||||
):
|
||||
""" run a query against PhotosDB to extract the photos based on user supply criteria
|
||||
used by query and export commands
|
||||
@@ -2118,6 +2146,17 @@ def _query(
|
||||
if has_raw:
|
||||
photos = [p for p in photos if p.has_raw]
|
||||
|
||||
if has_comment:
|
||||
photos = [p for p in photos if p.comments]
|
||||
elif no_comment:
|
||||
photos = [p for p in photos if not p.comments]
|
||||
|
||||
if has_likes:
|
||||
photos = [p for p in photos if p.likes]
|
||||
elif no_likes:
|
||||
photos = [p for p in photos if not p.likes]
|
||||
|
||||
|
||||
return photos
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.36.0"
|
||||
__version__ = "0.36.1"
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ from osxphotos.exiftool import get_exiftool_path
|
||||
CLI_PHOTOS_DB = "tests/Test-10.15.1.photoslibrary"
|
||||
LIVE_PHOTOS_DB = "tests/Test-Cloud-10.15.1.photoslibrary"
|
||||
RAW_PHOTOS_DB = "tests/Test-RAW-10.15.1.photoslibrary"
|
||||
COMMENTS_PHOTOS_DB = "tests/Test-Cloud-10.15.6.photoslibrary"
|
||||
PLACES_PHOTOS_DB = "tests/Test-Places-Catalina-10_15_1.photoslibrary"
|
||||
PLACES_PHOTOS_DB_13 = "tests/Test-Places-High-Sierra-10.13.6.photoslibrary"
|
||||
PHOTOS_DB_15_4 = "tests/Test-10.15.4.photoslibrary"
|
||||
@@ -419,6 +420,22 @@ CLI_EXPORT_UUID_FROM_FILE_FILENAMES = [
|
||||
"wedding_edited.jpeg",
|
||||
]
|
||||
|
||||
UUID_HAS_COMMENTS = [
|
||||
"4E4944A0-3E5C-4028-9600-A8709F2FA1DB",
|
||||
"4AD7C8EF-2991-4519-9D3A-7F44A6F031BE",
|
||||
"7572C53E-1D6A-410C-A2B1-18CCA3B5AD9F",
|
||||
]
|
||||
UUID_NO_COMMENTS = ["4F835581-5AB9-4DEC-9971-3E64A0894B04"]
|
||||
UUID_HAS_LIKES = [
|
||||
"C008048F-8767-4992-85B8-13E798F6DC3C",
|
||||
"65BADBD7-A50C-4956-96BA-1BB61155DA17",
|
||||
"4AD7C8EF-2991-4519-9D3A-7F44A6F031BE",
|
||||
]
|
||||
UUID_NO_LIKES = [
|
||||
"45099D34-A414-464F-94A2-60D6823679C8",
|
||||
"1C1C8F1F-826B-4A24-B1CB-56628946A834",
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def reset_globals():
|
||||
@@ -599,36 +616,92 @@ def test_query_uuid_from_file_1():
|
||||
assert sorted(UUID_EXPECTED_FROM_FILE) == sorted(uuid_got)
|
||||
|
||||
|
||||
def test_query_uuid_from_file_2():
|
||||
""" Test query with --uuid-from-file and --uuid """
|
||||
def test_query_has_comment():
|
||||
""" Test query with --has-comment """
|
||||
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,
|
||||
],
|
||||
["--json", "--db", os.path.join(cwd, COMMENTS_PHOTOS_DB), "--has-comment"],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
# build list of uuids we got from the output JSON
|
||||
json_got = json.loads(result.output)
|
||||
uuid_got = [photo["uuid"] for photo in json_got]
|
||||
uuid_expected = UUID_EXPECTED_FROM_FILE.copy()
|
||||
uuid_expected.append(UUID_NOT_FROM_FILE)
|
||||
assert sorted(uuid_expected) == sorted(uuid_got)
|
||||
assert sorted(uuid_got) == sorted(UUID_HAS_COMMENTS)
|
||||
|
||||
|
||||
def test_query_no_comment():
|
||||
""" Test query with --no-comment """
|
||||
import json
|
||||
import os
|
||||
import os.path
|
||||
from osxphotos.__main__ import query
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
result = runner.invoke(
|
||||
query, ["--json", "--db", os.path.join(cwd, COMMENTS_PHOTOS_DB), "--no-comment"]
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
# build list of uuids we got from the output JSON
|
||||
json_got = json.loads(result.output)
|
||||
uuid_got = [photo["uuid"] for photo in json_got]
|
||||
for uuid in UUID_NO_COMMENTS:
|
||||
assert uuid in uuid_got
|
||||
for uuid in uuid_got:
|
||||
assert uuid not in UUID_HAS_COMMENTS
|
||||
|
||||
|
||||
def test_query_has_likes():
|
||||
""" Test query with --has-likes"""
|
||||
import json
|
||||
import os
|
||||
import os.path
|
||||
from osxphotos.__main__ import query
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
result = runner.invoke(
|
||||
query,
|
||||
["--json", "--db", os.path.join(cwd, COMMENTS_PHOTOS_DB), "--has-likes"],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
# build list of uuids we got from the output JSON
|
||||
json_got = json.loads(result.output)
|
||||
uuid_got = [photo["uuid"] for photo in json_got]
|
||||
assert sorted(uuid_got) == sorted(UUID_HAS_LIKES)
|
||||
|
||||
|
||||
def test_query_no_likes():
|
||||
""" Test query with --no-likes"""
|
||||
import json
|
||||
import os
|
||||
import os.path
|
||||
from osxphotos.__main__ import query
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
result = runner.invoke(
|
||||
query, ["--json", "--db", os.path.join(cwd, COMMENTS_PHOTOS_DB), "--no-likes"]
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
# build list of uuids we got from the output JSON
|
||||
json_got = json.loads(result.output)
|
||||
uuid_got = [photo["uuid"] for photo in json_got]
|
||||
for uuid in UUID_NO_LIKES:
|
||||
assert uuid in uuid_got
|
||||
for uuid in uuid_got:
|
||||
assert uuid not in UUID_HAS_LIKES
|
||||
|
||||
|
||||
def test_export():
|
||||
|
||||
Reference in New Issue
Block a user