Added --query-eval, implements #280
This commit is contained in:
13
README.md
13
README.md
@@ -315,6 +315,19 @@ Options:
|
|||||||
albums.
|
albums.
|
||||||
|
|
||||||
--not-in-album Search for photos that are not in any albums.
|
--not-in-album Search for photos that are not in any albums.
|
||||||
|
--query-eval CRITERIA Evaluate CRITERIA to filter photos. CRITERIA
|
||||||
|
will be evaluated in context of the following
|
||||||
|
list comprehension: `photos = [photo for photo
|
||||||
|
in photos if CRITERIA]` where photo represents
|
||||||
|
a PhotoInfo object. For example: `--query-eval
|
||||||
|
photo.favorite` returns all photos that have
|
||||||
|
been favorited and is equivalent to
|
||||||
|
--favorite. You may specify more than one
|
||||||
|
CRITERIA by using --query-eval multiple times.
|
||||||
|
See https://rhettbull.github.io/osxphotos/ for
|
||||||
|
additional documentation on the PhotoInfo
|
||||||
|
class.
|
||||||
|
|
||||||
--missing Export only photos missing from the Photos
|
--missing Export only photos missing from the Photos
|
||||||
library; must be used with --download-missing.
|
library; must be used with --download-missing.
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
""" version info """
|
""" version info """
|
||||||
|
|
||||||
__version__ = "0.41.9"
|
__version__ = "0.41.10"
|
||||||
|
|||||||
@@ -447,6 +447,19 @@ def query_options(f):
|
|||||||
is_flag=True,
|
is_flag=True,
|
||||||
help="Search for photos that are not in any albums.",
|
help="Search for photos that are not in any albums.",
|
||||||
),
|
),
|
||||||
|
o(
|
||||||
|
"--query-eval",
|
||||||
|
metavar="CRITERIA",
|
||||||
|
multiple=True,
|
||||||
|
help="Evaluate CRITERIA to filter photos. "
|
||||||
|
"CRITERIA will be evaluated in context of the following list comprehension: "
|
||||||
|
"`photos = [photo for photo in photos if CRITERIA]` "
|
||||||
|
"where photo represents a PhotoInfo object. "
|
||||||
|
"For example: `--query-eval photo.favorite` returns all photos that have been "
|
||||||
|
"favorited and is equivalent to --favorite. "
|
||||||
|
"You may specify more than one CRITERIA by using --query-eval multiple times. "
|
||||||
|
"See https://rhettbull.github.io/osxphotos/ for additional documentation on the PhotoInfo class.",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
for o in options[::-1]:
|
for o in options[::-1]:
|
||||||
f = o(f)
|
f = o(f)
|
||||||
@@ -984,6 +997,7 @@ def export(
|
|||||||
beta,
|
beta,
|
||||||
in_album,
|
in_album,
|
||||||
not_in_album,
|
not_in_album,
|
||||||
|
query_eval,
|
||||||
):
|
):
|
||||||
"""Export photos from the Photos database.
|
"""Export photos from the Photos database.
|
||||||
Export path DEST is required.
|
Export path DEST is required.
|
||||||
@@ -1131,6 +1145,7 @@ def export(
|
|||||||
only_new = cfg.only_new
|
only_new = cfg.only_new
|
||||||
in_album = cfg.in_album
|
in_album = cfg.in_album
|
||||||
not_in_album = cfg.not_in_album
|
not_in_album = cfg.not_in_album
|
||||||
|
query_eval = cfg.query_eval
|
||||||
|
|
||||||
# config file might have changed verbose
|
# config file might have changed verbose
|
||||||
VERBOSE = bool(verbose)
|
VERBOSE = bool(verbose)
|
||||||
@@ -1433,6 +1448,7 @@ def export(
|
|||||||
# skip missing bursts if using --download-missing by itself as AppleScript otherwise causes errors
|
# skip missing bursts if using --download-missing by itself as AppleScript otherwise causes errors
|
||||||
missing_bursts=(download_missing and use_photokit) or not download_missing,
|
missing_bursts=(download_missing and use_photokit) or not download_missing,
|
||||||
name=name,
|
name=name,
|
||||||
|
query_eval=query_eval,
|
||||||
)
|
)
|
||||||
|
|
||||||
if photos:
|
if photos:
|
||||||
@@ -1718,6 +1734,7 @@ def query(
|
|||||||
is_reference,
|
is_reference,
|
||||||
in_album,
|
in_album,
|
||||||
not_in_album,
|
not_in_album,
|
||||||
|
query_eval,
|
||||||
):
|
):
|
||||||
"""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"
|
||||||
@@ -1744,6 +1761,7 @@ def query(
|
|||||||
to_time,
|
to_time,
|
||||||
label,
|
label,
|
||||||
is_reference,
|
is_reference,
|
||||||
|
query_eval,
|
||||||
]
|
]
|
||||||
exclusive = [
|
exclusive = [
|
||||||
(favorite, not_favorite),
|
(favorite, not_favorite),
|
||||||
@@ -1866,6 +1884,7 @@ def query(
|
|||||||
in_album=in_album,
|
in_album=in_album,
|
||||||
not_in_album=not_in_album,
|
not_in_album=not_in_album,
|
||||||
name=name,
|
name=name,
|
||||||
|
query_eval=query_eval,
|
||||||
)
|
)
|
||||||
|
|
||||||
# below needed for to make CliRunner work for testing
|
# below needed for to make CliRunner work for testing
|
||||||
@@ -2044,6 +2063,7 @@ def _query(
|
|||||||
burst_photos=None,
|
burst_photos=None,
|
||||||
missing_bursts=None,
|
missing_bursts=None,
|
||||||
name=None,
|
name=None,
|
||||||
|
query_eval=None,
|
||||||
):
|
):
|
||||||
"""Run a query against PhotosDB to extract the photos based on user supply criteria used by query and export commands
|
"""Run a query against PhotosDB to extract the photos based on user supply criteria used by query and export commands
|
||||||
|
|
||||||
@@ -2338,6 +2358,16 @@ def _query(
|
|||||||
)
|
)
|
||||||
photos = photo_list
|
photos = photo_list
|
||||||
|
|
||||||
|
if query_eval:
|
||||||
|
for q in query_eval:
|
||||||
|
query_string = f"[photo for photo in photos if {q}]"
|
||||||
|
try:
|
||||||
|
photos = eval(query_string)
|
||||||
|
except Exception as e:
|
||||||
|
raise click.BadOptionUsage(
|
||||||
|
"query_eval", f"Invalid query-eval CRITERIA: {e}"
|
||||||
|
)
|
||||||
|
|
||||||
return photos
|
return photos
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5768,3 +5768,34 @@ def test_export_name():
|
|||||||
files = glob.glob("*")
|
files = glob.glob("*")
|
||||||
assert len(files) == 1
|
assert len(files) == 1
|
||||||
|
|
||||||
|
def test_query_eval():
|
||||||
|
""" test export --query-eval """
|
||||||
|
import glob
|
||||||
|
from osxphotos.cli 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_7), ".", "-V", "--query-eval", "'DSC03584' in photo.original_filename"]
|
||||||
|
)
|
||||||
|
assert result.exit_code == 0
|
||||||
|
files = glob.glob("*")
|
||||||
|
assert len(files) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_bad_query_eval():
|
||||||
|
""" test export --query-eval with bad input """
|
||||||
|
import glob
|
||||||
|
from osxphotos.cli 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_7), ".", "-V", "--query-eval", "'DSC03584' in photo.originalfilename"]
|
||||||
|
)
|
||||||
|
assert result.exit_code != 0
|
||||||
|
assert "Error: Invalid query-eval CRITERIA" in result.output
|
||||||
Reference in New Issue
Block a user