Added --has-comment/--has-likes to CLI, issue #240
This commit is contained in:
@@ -221,6 +221,10 @@ Options:
|
|||||||
2000-01-12T12:00:00,
|
2000-01-12T12:00:00,
|
||||||
2001-01-12T12:00:00-07:00, or 2000-12-31
|
2001-01-12T12:00:00-07:00, or 2000-12-31
|
||||||
(ISO 8601).
|
(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'
|
--deleted Include photos from the 'Recently Deleted'
|
||||||
folder.
|
folder.
|
||||||
--deleted-only Include only photos from the 'Recently
|
--deleted-only Include only photos from the 'Recently
|
||||||
@@ -542,6 +546,7 @@ Substitution Description
|
|||||||
(Photos 5 only)
|
(Photos 5 only)
|
||||||
{label_normalized} All lower case version of 'label' (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} 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
|
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).",
|
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(),
|
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]:
|
for o in options[::-1]:
|
||||||
f = o(f)
|
f = o(f)
|
||||||
@@ -982,6 +986,10 @@ def query(
|
|||||||
label,
|
label,
|
||||||
deleted,
|
deleted,
|
||||||
deleted_only,
|
deleted_only,
|
||||||
|
has_comment,
|
||||||
|
no_comment,
|
||||||
|
has_likes,
|
||||||
|
no_likes,
|
||||||
):
|
):
|
||||||
""" Query the Photos database using 1 or more search options;
|
""" Query the Photos database using 1 or more search options;
|
||||||
if more than one option is provided, they are treated as "AND"
|
if more than one option is provided, they are treated as "AND"
|
||||||
@@ -1026,6 +1034,8 @@ def query(
|
|||||||
(any(place), no_place),
|
(any(place), no_place),
|
||||||
(deleted, deleted_only),
|
(deleted, deleted_only),
|
||||||
(shared, not_shared),
|
(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
|
# 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(
|
if any(all(bb) for bb in exclusive) or not any(
|
||||||
@@ -1112,6 +1122,10 @@ def query(
|
|||||||
label=label,
|
label=label,
|
||||||
deleted=deleted,
|
deleted=deleted,
|
||||||
deleted_only=deleted_only,
|
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
|
# below needed for to make CliRunner work for testing
|
||||||
@@ -1395,6 +1409,10 @@ def export(
|
|||||||
edited_suffix,
|
edited_suffix,
|
||||||
place,
|
place,
|
||||||
no_place,
|
no_place,
|
||||||
|
has_comment,
|
||||||
|
no_comment,
|
||||||
|
has_likes,
|
||||||
|
no_likes,
|
||||||
no_extended_attributes,
|
no_extended_attributes,
|
||||||
label,
|
label,
|
||||||
deleted,
|
deleted,
|
||||||
@@ -1442,6 +1460,8 @@ def export(
|
|||||||
(skip_edited, skip_original_if_edited),
|
(skip_edited, skip_original_if_edited),
|
||||||
(export_as_hardlink, convert_to_jpeg),
|
(export_as_hardlink, convert_to_jpeg),
|
||||||
(shared, not_shared),
|
(shared, not_shared),
|
||||||
|
(has_comment, no_comment),
|
||||||
|
(has_likes, no_likes),
|
||||||
]
|
]
|
||||||
if any(all(bb) for bb in exclusive):
|
if any(all(bb) for bb in exclusive):
|
||||||
click.echo("Incompatible export options", err=True)
|
click.echo("Incompatible export options", err=True)
|
||||||
@@ -1580,6 +1600,10 @@ def export(
|
|||||||
label=label,
|
label=label,
|
||||||
deleted=deleted,
|
deleted=deleted,
|
||||||
deleted_only=deleted_only,
|
deleted_only=deleted_only,
|
||||||
|
has_comment=has_comment,
|
||||||
|
no_comment=no_comment,
|
||||||
|
has_likes=has_likes,
|
||||||
|
no_likes=no_likes,
|
||||||
)
|
)
|
||||||
|
|
||||||
if photos:
|
if photos:
|
||||||
@@ -1899,6 +1923,10 @@ def _query(
|
|||||||
label=None,
|
label=None,
|
||||||
deleted=False,
|
deleted=False,
|
||||||
deleted_only=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
|
""" run a query against PhotosDB to extract the photos based on user supply criteria
|
||||||
used by query and export commands
|
used by query and export commands
|
||||||
@@ -2118,6 +2146,17 @@ def _query(
|
|||||||
if has_raw:
|
if has_raw:
|
||||||
photos = [p for p in photos if p.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
|
return photos
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
""" version info """
|
""" 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"
|
CLI_PHOTOS_DB = "tests/Test-10.15.1.photoslibrary"
|
||||||
LIVE_PHOTOS_DB = "tests/Test-Cloud-10.15.1.photoslibrary"
|
LIVE_PHOTOS_DB = "tests/Test-Cloud-10.15.1.photoslibrary"
|
||||||
RAW_PHOTOS_DB = "tests/Test-RAW-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 = "tests/Test-Places-Catalina-10_15_1.photoslibrary"
|
||||||
PLACES_PHOTOS_DB_13 = "tests/Test-Places-High-Sierra-10.13.6.photoslibrary"
|
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_4 = "tests/Test-10.15.4.photoslibrary"
|
||||||
@@ -419,6 +420,22 @@ CLI_EXPORT_UUID_FROM_FILE_FILENAMES = [
|
|||||||
"wedding_edited.jpeg",
|
"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)
|
@pytest.fixture(autouse=True)
|
||||||
def reset_globals():
|
def reset_globals():
|
||||||
@@ -599,36 +616,92 @@ def test_query_uuid_from_file_1():
|
|||||||
assert sorted(UUID_EXPECTED_FROM_FILE) == sorted(uuid_got)
|
assert sorted(UUID_EXPECTED_FROM_FILE) == sorted(uuid_got)
|
||||||
|
|
||||||
|
|
||||||
def test_query_uuid_from_file_2():
|
def test_query_has_comment():
|
||||||
""" Test query with --uuid-from-file and --uuid """
|
""" Test query with --has-comment """
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import osxphotos
|
|
||||||
from osxphotos.__main__ import query
|
from osxphotos.__main__ import query
|
||||||
|
|
||||||
runner = CliRunner()
|
runner = CliRunner()
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
result = runner.invoke(
|
result = runner.invoke(
|
||||||
query,
|
query,
|
||||||
[
|
["--json", "--db", os.path.join(cwd, COMMENTS_PHOTOS_DB), "--has-comment"],
|
||||||
"--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
|
assert result.exit_code == 0
|
||||||
|
|
||||||
# build list of uuids we got from the output JSON
|
# build list of uuids we got from the output JSON
|
||||||
json_got = json.loads(result.output)
|
json_got = json.loads(result.output)
|
||||||
uuid_got = [photo["uuid"] for photo in json_got]
|
uuid_got = [photo["uuid"] for photo in json_got]
|
||||||
uuid_expected = UUID_EXPECTED_FROM_FILE.copy()
|
assert sorted(uuid_got) == sorted(UUID_HAS_COMMENTS)
|
||||||
uuid_expected.append(UUID_NOT_FROM_FILE)
|
|
||||||
assert sorted(uuid_expected) == sorted(uuid_got)
|
|
||||||
|
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():
|
def test_export():
|
||||||
|
|||||||
Reference in New Issue
Block a user