Added --query-eval, implements #280
This commit is contained in:
13
README.md
13
README.md
@@ -315,6 +315,19 @@ Options:
|
||||
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
|
||||
library; must be used with --download-missing.
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.41.9"
|
||||
__version__ = "0.41.10"
|
||||
|
||||
@@ -447,6 +447,19 @@ def query_options(f):
|
||||
is_flag=True,
|
||||
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]:
|
||||
f = o(f)
|
||||
@@ -984,6 +997,7 @@ def export(
|
||||
beta,
|
||||
in_album,
|
||||
not_in_album,
|
||||
query_eval,
|
||||
):
|
||||
"""Export photos from the Photos database.
|
||||
Export path DEST is required.
|
||||
@@ -1131,6 +1145,7 @@ def export(
|
||||
only_new = cfg.only_new
|
||||
in_album = cfg.in_album
|
||||
not_in_album = cfg.not_in_album
|
||||
query_eval = cfg.query_eval
|
||||
|
||||
# config file might have changed verbose
|
||||
VERBOSE = bool(verbose)
|
||||
@@ -1433,6 +1448,7 @@ def export(
|
||||
# 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,
|
||||
name=name,
|
||||
query_eval=query_eval,
|
||||
)
|
||||
|
||||
if photos:
|
||||
@@ -1718,6 +1734,7 @@ def query(
|
||||
is_reference,
|
||||
in_album,
|
||||
not_in_album,
|
||||
query_eval,
|
||||
):
|
||||
"""Query the Photos database using 1 or more search options;
|
||||
if more than one option is provided, they are treated as "AND"
|
||||
@@ -1744,6 +1761,7 @@ def query(
|
||||
to_time,
|
||||
label,
|
||||
is_reference,
|
||||
query_eval,
|
||||
]
|
||||
exclusive = [
|
||||
(favorite, not_favorite),
|
||||
@@ -1866,6 +1884,7 @@ def query(
|
||||
in_album=in_album,
|
||||
not_in_album=not_in_album,
|
||||
name=name,
|
||||
query_eval=query_eval,
|
||||
)
|
||||
|
||||
# below needed for to make CliRunner work for testing
|
||||
@@ -2044,6 +2063,7 @@ def _query(
|
||||
burst_photos=None,
|
||||
missing_bursts=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
|
||||
|
||||
@@ -2338,6 +2358,16 @@ def _query(
|
||||
)
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -5768,3 +5768,34 @@ def test_export_name():
|
||||
files = glob.glob("*")
|
||||
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