Added --location, --no-location, #474
This commit is contained in:
@@ -616,6 +616,10 @@ Options:
|
|||||||
geolocation info
|
geolocation info
|
||||||
--no-place Search for photos with no associated place
|
--no-place Search for photos with no associated place
|
||||||
name info (no reverse geolocation info)
|
name info (no reverse geolocation info)
|
||||||
|
--location Search for photos with associated location
|
||||||
|
info (e.g. GPS coordinates)
|
||||||
|
--no-location Search for photos with no associated location
|
||||||
|
info (e.g. no GPS coordinates)
|
||||||
--label LABEL Search for photos with image classification
|
--label LABEL Search for photos with image classification
|
||||||
label LABEL (Photos 5 only). If more than one
|
label LABEL (Photos 5 only). If more than one
|
||||||
label, treated as "OR", e.g. find photos
|
label, treated as "OR", e.g. find photos
|
||||||
@@ -1583,7 +1587,7 @@ Substitution Description
|
|||||||
{lf} A line feed: '\n', alias for {newline}
|
{lf} A line feed: '\n', alias for {newline}
|
||||||
{cr} A carriage return: '\r'
|
{cr} A carriage return: '\r'
|
||||||
{crlf} a carriage return + line feed: '\r\n'
|
{crlf} a carriage return + line feed: '\r\n'
|
||||||
{osxphotos_version} The osxphotos version, e.g. '0.42.43'
|
{osxphotos_version} The osxphotos version, e.g. '0.42.44'
|
||||||
{osxphotos_cmd_line} The full command line used to run osxphotos
|
{osxphotos_cmd_line} The full command line used to run osxphotos
|
||||||
|
|
||||||
The following substitutions may result in multiple values. Thus if specified for
|
The following substitutions may result in multiple values. Thus if specified for
|
||||||
@@ -3382,7 +3386,7 @@ The following template field substitutions are availabe for use the templating s
|
|||||||
|{lf}|A line feed: '\n', alias for {newline}|
|
|{lf}|A line feed: '\n', alias for {newline}|
|
||||||
|{cr}|A carriage return: '\r'|
|
|{cr}|A carriage return: '\r'|
|
||||||
|{crlf}|a carriage return + line feed: '\r\n'|
|
|{crlf}|a carriage return + line feed: '\r\n'|
|
||||||
|{osxphotos_version}|The osxphotos version, e.g. '0.42.43'|
|
|{osxphotos_version}|The osxphotos version, e.g. '0.42.44'|
|
||||||
|{osxphotos_cmd_line}|The full command line used to run osxphotos|
|
|{osxphotos_cmd_line}|The full command line used to run osxphotos|
|
||||||
|{album}|Album(s) photo is contained in|
|
|{album}|Album(s) photo is contained in|
|
||||||
|{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder|
|
|{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
""" version info """
|
""" version info """
|
||||||
|
|
||||||
__version__ = "0.42.43"
|
__version__ = "0.42.44"
|
||||||
|
|||||||
@@ -332,6 +332,16 @@ def QUERY_OPTIONS(f):
|
|||||||
is_flag=True,
|
is_flag=True,
|
||||||
help="Search for photos with no associated place name info (no reverse geolocation info)",
|
help="Search for photos with no associated place name info (no reverse geolocation info)",
|
||||||
),
|
),
|
||||||
|
o(
|
||||||
|
"--location",
|
||||||
|
is_flag=True,
|
||||||
|
help="Search for photos with associated location info (e.g. GPS coordinates)",
|
||||||
|
),
|
||||||
|
o(
|
||||||
|
"--no-location",
|
||||||
|
is_flag=True,
|
||||||
|
help="Search for photos with no associated location info (e.g. no GPS coordinates)",
|
||||||
|
),
|
||||||
o(
|
o(
|
||||||
"--label",
|
"--label",
|
||||||
metavar="LABEL",
|
metavar="LABEL",
|
||||||
@@ -1104,6 +1114,8 @@ def export(
|
|||||||
original_suffix,
|
original_suffix,
|
||||||
place,
|
place,
|
||||||
no_place,
|
no_place,
|
||||||
|
location,
|
||||||
|
no_location,
|
||||||
has_comment,
|
has_comment,
|
||||||
no_comment,
|
no_comment,
|
||||||
has_likes,
|
has_likes,
|
||||||
@@ -1263,6 +1275,8 @@ def export(
|
|||||||
original_suffix = cfg.original_suffix
|
original_suffix = cfg.original_suffix
|
||||||
place = cfg.place
|
place = cfg.place
|
||||||
no_place = cfg.no_place
|
no_place = cfg.no_place
|
||||||
|
location = cfg.location
|
||||||
|
no_location = cfg.no_location
|
||||||
has_comment = cfg.has_comment
|
has_comment = cfg.has_comment
|
||||||
no_comment = cfg.no_comment
|
no_comment = cfg.no_comment
|
||||||
has_likes = cfg.has_likes
|
has_likes = cfg.has_likes
|
||||||
@@ -1323,6 +1337,7 @@ def export(
|
|||||||
("has_comment", "no_comment"),
|
("has_comment", "no_comment"),
|
||||||
("has_likes", "no_likes"),
|
("has_likes", "no_likes"),
|
||||||
("in_album", "not_in_album"),
|
("in_album", "not_in_album"),
|
||||||
|
("location", "no_location"),
|
||||||
]
|
]
|
||||||
dependent_options = [
|
dependent_options = [
|
||||||
("missing", ("download_missing", "use_photos_export")),
|
("missing", ("download_missing", "use_photos_export")),
|
||||||
@@ -1576,6 +1591,8 @@ def export(
|
|||||||
has_raw=has_raw,
|
has_raw=has_raw,
|
||||||
place=place,
|
place=place,
|
||||||
no_place=no_place,
|
no_place=no_place,
|
||||||
|
location=location,
|
||||||
|
no_location=no_location,
|
||||||
label=label,
|
label=label,
|
||||||
deleted=deleted,
|
deleted=deleted,
|
||||||
deleted_only=deleted_only,
|
deleted_only=deleted_only,
|
||||||
@@ -1979,6 +1996,8 @@ def query(
|
|||||||
has_raw,
|
has_raw,
|
||||||
place,
|
place,
|
||||||
no_place,
|
no_place,
|
||||||
|
location,
|
||||||
|
no_location,
|
||||||
label,
|
label,
|
||||||
deleted,
|
deleted,
|
||||||
deleted_only,
|
deleted_only,
|
||||||
@@ -2051,6 +2070,7 @@ def query(
|
|||||||
(has_comment, no_comment),
|
(has_comment, no_comment),
|
||||||
(has_likes, no_likes),
|
(has_likes, no_likes),
|
||||||
(in_album, not_in_album),
|
(in_album, not_in_album),
|
||||||
|
(location, no_location),
|
||||||
]
|
]
|
||||||
# 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(
|
||||||
@@ -2136,6 +2156,8 @@ def query(
|
|||||||
has_raw=has_raw,
|
has_raw=has_raw,
|
||||||
place=place,
|
place=place,
|
||||||
no_place=no_place,
|
no_place=no_place,
|
||||||
|
location=location,
|
||||||
|
no_location=no_location,
|
||||||
label=label,
|
label=label,
|
||||||
deleted=deleted,
|
deleted=deleted,
|
||||||
deleted_only=deleted_only,
|
deleted_only=deleted_only,
|
||||||
|
|||||||
@@ -3254,6 +3254,11 @@ class PhotosDB:
|
|||||||
if options.deleted_only:
|
if options.deleted_only:
|
||||||
photos = [p for p in photos if p.intrash]
|
photos = [p for p in photos if p.intrash]
|
||||||
|
|
||||||
|
if options.location:
|
||||||
|
photos = [p for p in photos if p.location != (None, None)]
|
||||||
|
elif options.no_location:
|
||||||
|
photos = [p for p in photos if p.location == (None, None)]
|
||||||
|
|
||||||
return photos
|
return photos
|
||||||
|
|
||||||
def _duplicate_signature(self, uuid):
|
def _duplicate_signature(self, uuid):
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ class QueryOptions:
|
|||||||
regex: Optional[Iterable[Tuple[str, str]]] = None
|
regex: Optional[Iterable[Tuple[str, str]]] = None
|
||||||
query_eval: Optional[Iterable[str]] = None
|
query_eval: Optional[Iterable[str]] = None
|
||||||
duplicate: Optional[bool] = None
|
duplicate: Optional[bool] = None
|
||||||
|
location: Optional[bool] = None
|
||||||
|
no_location: Optional[bool] = None
|
||||||
|
|
||||||
def asdict(self):
|
def asdict(self):
|
||||||
return asdict(self)
|
return asdict(self)
|
||||||
|
|||||||
@@ -771,6 +771,9 @@ UUID_DUPLICATES = [
|
|||||||
"52083079-73D5-4921-AC1B-FE76F279133F",
|
"52083079-73D5-4921-AC1B-FE76F279133F",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
UUID_LOCATION = "D79B8D77-BFFC-460B-9312-034F2877D35B" # Pumkins2.jpg
|
||||||
|
UUID_NO_LOCATION = "6191423D-8DB8-4D4C-92BE-9BBBA308AAC4" # Tulips.jpg"
|
||||||
|
|
||||||
|
|
||||||
def modify_file(filename):
|
def modify_file(filename):
|
||||||
"""appends data to a file to modify it"""
|
"""appends data to a file to modify it"""
|
||||||
@@ -1147,6 +1150,52 @@ def test_query_duplicate():
|
|||||||
assert sorted(uuid_got) == sorted(UUID_DUPLICATES)
|
assert sorted(uuid_got) == sorted(UUID_DUPLICATES)
|
||||||
|
|
||||||
|
|
||||||
|
def test_query_location():
|
||||||
|
"""Test query with --location"""
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
from osxphotos.cli import query
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
cwd = os.getcwd()
|
||||||
|
result = runner.invoke(
|
||||||
|
query,
|
||||||
|
["--json", "--db", os.path.join(cwd, CLI_PHOTOS_DB), "--location"],
|
||||||
|
)
|
||||||
|
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 UUID_LOCATION in uuid_got
|
||||||
|
assert UUID_NO_LOCATION not in uuid_got
|
||||||
|
|
||||||
|
|
||||||
|
def test_query_no_location():
|
||||||
|
"""Test query with --no-location"""
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
from osxphotos.cli import query
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
cwd = os.getcwd()
|
||||||
|
result = runner.invoke(
|
||||||
|
query,
|
||||||
|
["--json", "--db", os.path.join(cwd, CLI_PHOTOS_DB), "--no-location"],
|
||||||
|
)
|
||||||
|
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 UUID_NO_LOCATION in uuid_got
|
||||||
|
assert UUID_LOCATION not in uuid_got
|
||||||
|
|
||||||
|
|
||||||
def test_export():
|
def test_export():
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
|
|||||||
Reference in New Issue
Block a user