@@ -380,6 +380,31 @@ def QUERY_OPTIONS(f):
|
||||
multiple=True,
|
||||
type=int,
|
||||
),
|
||||
o(
|
||||
"--added-before",
|
||||
metavar="DATE",
|
||||
help="Search for items added to the library before a specific date/time, "
|
||||
"e.g. --added-before e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).",
|
||||
type=DateTimeISO8601(),
|
||||
),
|
||||
o(
|
||||
"--added-after",
|
||||
metavar="DATE",
|
||||
help="Search for items added to the libray after a specific date/time, "
|
||||
"e.g. --added-after e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).",
|
||||
type=DateTimeISO8601(),
|
||||
),
|
||||
o(
|
||||
"--added-in-last",
|
||||
metavar="TIME_DELTA",
|
||||
help="Search for items added to the library in the last TIME_DELTA, "
|
||||
"where TIME_DELTA is a string like "
|
||||
"'12 hrs', '1 day', '1d', '1 week', '2weeks', '1 month', '1 year'. "
|
||||
"for example, `--added-in-last 7d` and `--added-in-last '1 week'` are equivalent. "
|
||||
"months are assumed to be 30 days and years are assumed to be 365 days. "
|
||||
"Common English abbreviations are accepted, e.g. d, day, days or m, min, minutes.",
|
||||
type=TimeOffset(),
|
||||
),
|
||||
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."),
|
||||
@@ -569,4 +594,3 @@ def check_version():
|
||||
"to suppress this message and prevent osxphotos from checking for latest version.",
|
||||
err=True,
|
||||
)
|
||||
|
||||
|
||||
@@ -672,145 +672,148 @@ def export(
|
||||
cli_obj,
|
||||
db,
|
||||
photos_library,
|
||||
keyword,
|
||||
person,
|
||||
album,
|
||||
folder,
|
||||
uuid,
|
||||
name,
|
||||
uuid_from_file,
|
||||
title,
|
||||
no_title,
|
||||
description,
|
||||
no_description,
|
||||
uti,
|
||||
ignore_case,
|
||||
edited,
|
||||
external_edit,
|
||||
favorite,
|
||||
not_favorite,
|
||||
hidden,
|
||||
not_hidden,
|
||||
shared,
|
||||
not_shared,
|
||||
from_date,
|
||||
to_date,
|
||||
from_time,
|
||||
to_time,
|
||||
year,
|
||||
verbose,
|
||||
timestamp,
|
||||
no_progress,
|
||||
missing,
|
||||
update,
|
||||
force_update,
|
||||
ignore_signature,
|
||||
only_new,
|
||||
dry_run,
|
||||
export_as_hardlink,
|
||||
touch_file,
|
||||
overwrite,
|
||||
retry,
|
||||
export_by_date,
|
||||
skip_edited,
|
||||
skip_original_if_edited,
|
||||
skip_bursts,
|
||||
skip_live,
|
||||
skip_raw,
|
||||
skip_uuid,
|
||||
skip_uuid_from_file,
|
||||
person_keyword,
|
||||
add_exported_to_album,
|
||||
add_missing_to_album,
|
||||
add_skipped_to_album,
|
||||
added_after,
|
||||
added_before,
|
||||
added_in_last,
|
||||
album_keyword,
|
||||
keyword_template,
|
||||
replace_keywords,
|
||||
description_template,
|
||||
finder_tag_template,
|
||||
finder_tag_keywords,
|
||||
xattr_template,
|
||||
current_name,
|
||||
convert_to_jpeg,
|
||||
jpeg_quality,
|
||||
sidecar,
|
||||
sidecar_drop_ext,
|
||||
only_photos,
|
||||
only_movies,
|
||||
album,
|
||||
beta,
|
||||
burst,
|
||||
not_burst,
|
||||
live,
|
||||
not_live,
|
||||
download_missing,
|
||||
cleanup,
|
||||
config_only,
|
||||
convert_to_jpeg,
|
||||
current_name,
|
||||
deleted_only,
|
||||
deleted,
|
||||
description_template,
|
||||
description,
|
||||
dest,
|
||||
exiftool,
|
||||
exiftool_path,
|
||||
exiftool_option,
|
||||
directory,
|
||||
download_missing,
|
||||
dry_run,
|
||||
duplicate,
|
||||
edited_suffix,
|
||||
edited,
|
||||
exif,
|
||||
exiftool_merge_keywords,
|
||||
exiftool_merge_persons,
|
||||
ignore_date_modified,
|
||||
portrait,
|
||||
not_portrait,
|
||||
screenshot,
|
||||
not_screenshot,
|
||||
slow_mo,
|
||||
not_slow_mo,
|
||||
time_lapse,
|
||||
not_time_lapse,
|
||||
hdr,
|
||||
not_hdr,
|
||||
selfie,
|
||||
not_selfie,
|
||||
panorama,
|
||||
not_panorama,
|
||||
has_raw,
|
||||
directory,
|
||||
filename_template,
|
||||
jpeg_ext,
|
||||
strip,
|
||||
edited_suffix,
|
||||
original_suffix,
|
||||
place,
|
||||
no_place,
|
||||
location,
|
||||
no_location,
|
||||
has_comment,
|
||||
no_comment,
|
||||
has_likes,
|
||||
no_likes,
|
||||
label,
|
||||
deleted,
|
||||
deleted_only,
|
||||
use_photos_export,
|
||||
use_photokit,
|
||||
report,
|
||||
cleanup,
|
||||
add_exported_to_album,
|
||||
add_skipped_to_album,
|
||||
add_missing_to_album,
|
||||
exiftool_option,
|
||||
exiftool_path,
|
||||
exiftool,
|
||||
export_as_hardlink,
|
||||
export_by_date,
|
||||
exportdb,
|
||||
ramdb,
|
||||
tmpdir,
|
||||
load_config,
|
||||
save_config,
|
||||
config_only,
|
||||
is_reference,
|
||||
beta,
|
||||
external_edit,
|
||||
favorite,
|
||||
filename_template,
|
||||
finder_tag_keywords,
|
||||
finder_tag_template,
|
||||
folder,
|
||||
force_update,
|
||||
from_date,
|
||||
from_time,
|
||||
has_comment,
|
||||
has_likes,
|
||||
has_raw,
|
||||
hdr,
|
||||
hidden,
|
||||
ignore_case,
|
||||
ignore_date_modified,
|
||||
ignore_signature,
|
||||
in_album,
|
||||
not_in_album,
|
||||
min_size,
|
||||
is_reference,
|
||||
jpeg_ext,
|
||||
jpeg_quality,
|
||||
keyword_template,
|
||||
keyword,
|
||||
label,
|
||||
live,
|
||||
load_config,
|
||||
location,
|
||||
max_size,
|
||||
regex,
|
||||
selected,
|
||||
exif,
|
||||
query_eval,
|
||||
query_function,
|
||||
duplicate,
|
||||
min_size,
|
||||
missing,
|
||||
name,
|
||||
no_comment,
|
||||
no_description,
|
||||
no_likes,
|
||||
no_location,
|
||||
no_place,
|
||||
no_progress,
|
||||
no_title,
|
||||
not_burst,
|
||||
not_favorite,
|
||||
not_hdr,
|
||||
not_hidden,
|
||||
not_in_album,
|
||||
not_live,
|
||||
not_panorama,
|
||||
not_portrait,
|
||||
not_screenshot,
|
||||
not_selfie,
|
||||
not_shared,
|
||||
not_slow_mo,
|
||||
not_time_lapse,
|
||||
only_movies,
|
||||
only_new,
|
||||
only_photos,
|
||||
original_suffix,
|
||||
overwrite,
|
||||
panorama,
|
||||
person_keyword,
|
||||
person,
|
||||
place,
|
||||
portrait,
|
||||
post_command,
|
||||
post_function,
|
||||
preview,
|
||||
preview_suffix,
|
||||
preview_if_missing,
|
||||
profile,
|
||||
preview_suffix,
|
||||
preview,
|
||||
profile_sort,
|
||||
profile,
|
||||
query_eval,
|
||||
query_function,
|
||||
ramdb,
|
||||
regex,
|
||||
replace_keywords,
|
||||
report,
|
||||
retry,
|
||||
save_config,
|
||||
screenshot,
|
||||
selected,
|
||||
selfie,
|
||||
shared,
|
||||
sidecar_drop_ext,
|
||||
sidecar,
|
||||
skip_bursts,
|
||||
skip_edited,
|
||||
skip_live,
|
||||
skip_original_if_edited,
|
||||
skip_raw,
|
||||
skip_uuid_from_file,
|
||||
skip_uuid,
|
||||
slow_mo,
|
||||
strip,
|
||||
theme,
|
||||
time_lapse,
|
||||
timestamp,
|
||||
title,
|
||||
tmpdir,
|
||||
to_date,
|
||||
to_time,
|
||||
touch_file,
|
||||
update,
|
||||
use_photokit,
|
||||
use_photos_export,
|
||||
uti,
|
||||
uuid_from_file,
|
||||
uuid,
|
||||
verbose,
|
||||
xattr_template,
|
||||
year,
|
||||
debug, # debug, watch, breakpoint handled in cli/__init__.py
|
||||
watch,
|
||||
breakpoint,
|
||||
@@ -886,6 +889,9 @@ def export(
|
||||
|
||||
# re-set the local vars to the corresponding config value
|
||||
# this isn't elegant but avoids having to rewrite this function to use cfg.varname for every parameter
|
||||
added_after = cfg.added_after
|
||||
added_before = cfg.added_before
|
||||
added_in_last = cfg.added_in_last
|
||||
add_exported_to_album = cfg.add_exported_to_album
|
||||
add_missing_to_album = cfg.add_missing_to_album
|
||||
add_skipped_to_album = cfg.add_skipped_to_album
|
||||
@@ -1038,41 +1044,41 @@ def export(
|
||||
|
||||
# validate options
|
||||
exclusive_options = [
|
||||
("favorite", "not_favorite"),
|
||||
("hidden", "not_hidden"),
|
||||
("title", "no_title"),
|
||||
("description", "no_description"),
|
||||
("only_photos", "only_movies"),
|
||||
("burst", "not_burst"),
|
||||
("live", "not_live"),
|
||||
("portrait", "not_portrait"),
|
||||
("screenshot", "not_screenshot"),
|
||||
("slow_mo", "not_slow_mo"),
|
||||
("time_lapse", "not_time_lapse"),
|
||||
("hdr", "not_hdr"),
|
||||
("selfie", "not_selfie"),
|
||||
("panorama", "not_panorama"),
|
||||
("export_by_date", "directory"),
|
||||
("export_as_hardlink", "exiftool"),
|
||||
("place", "no_place"),
|
||||
("deleted", "deleted_only"),
|
||||
("skip_edited", "skip_original_if_edited"),
|
||||
("description", "no_description"),
|
||||
("export_as_hardlink", "convert_to_jpeg"),
|
||||
("export_as_hardlink", "download_missing"),
|
||||
("shared", "not_shared"),
|
||||
("export_as_hardlink", "exiftool"),
|
||||
("export_by_date", "directory"),
|
||||
("favorite", "not_favorite"),
|
||||
("has_comment", "no_comment"),
|
||||
("has_likes", "no_likes"),
|
||||
("hdr", "not_hdr"),
|
||||
("hidden", "not_hidden"),
|
||||
("in_album", "not_in_album"),
|
||||
("live", "not_live"),
|
||||
("location", "no_location"),
|
||||
("only_photos", "only_movies"),
|
||||
("panorama", "not_panorama"),
|
||||
("place", "no_place"),
|
||||
("portrait", "not_portrait"),
|
||||
("screenshot", "not_screenshot"),
|
||||
("selfie", "not_selfie"),
|
||||
("shared", "not_shared"),
|
||||
("skip_edited", "skip_original_if_edited"),
|
||||
("slow_mo", "not_slow_mo"),
|
||||
("time_lapse", "not_time_lapse"),
|
||||
("title", "no_title"),
|
||||
]
|
||||
dependent_options = [
|
||||
("missing", ("download_missing", "use_photos_export")),
|
||||
("jpeg_quality", ("convert_to_jpeg")),
|
||||
("ignore_signature", ("update", "force_update")),
|
||||
("only_new", ("update", "force_update")),
|
||||
("exiftool_option", ("exiftool")),
|
||||
("exiftool_merge_keywords", ("exiftool", "sidecar")),
|
||||
("exiftool_merge_persons", ("exiftool", "sidecar")),
|
||||
("exiftool_option", ("exiftool")),
|
||||
("ignore_signature", ("update", "force_update")),
|
||||
("jpeg_quality", ("convert_to_jpeg")),
|
||||
("missing", ("download_missing", "use_photos_export")),
|
||||
("only_new", ("update", "force_update")),
|
||||
]
|
||||
try:
|
||||
cfg.validate(exclusive=exclusive_options, dependent=dependent_options, cli=True)
|
||||
@@ -1267,83 +1273,86 @@ def export(
|
||||
photosdb._beta = beta
|
||||
|
||||
query_options = QueryOptions(
|
||||
keyword=keyword,
|
||||
person=person,
|
||||
added_after=added_after,
|
||||
added_before=added_before,
|
||||
added_in_last=added_in_last,
|
||||
album=album,
|
||||
folder=folder,
|
||||
uuid=uuid,
|
||||
title=title,
|
||||
no_title=no_title,
|
||||
burst_photos=export_bursts,
|
||||
burst=burst,
|
||||
cloudasset=False,
|
||||
deleted_only=deleted_only,
|
||||
deleted=deleted,
|
||||
description=description,
|
||||
no_description=no_description,
|
||||
ignore_case=ignore_case,
|
||||
duplicate=duplicate,
|
||||
edited=edited,
|
||||
exif=exif,
|
||||
external_edit=external_edit,
|
||||
favorite=favorite,
|
||||
not_favorite=not_favorite,
|
||||
hidden=hidden,
|
||||
not_hidden=not_hidden,
|
||||
missing=missing,
|
||||
not_missing=None,
|
||||
shared=shared,
|
||||
not_shared=not_shared,
|
||||
photos=photos,
|
||||
movies=movies,
|
||||
uti=uti,
|
||||
burst=burst,
|
||||
not_burst=not_burst,
|
||||
live=live,
|
||||
not_live=not_live,
|
||||
cloudasset=False,
|
||||
not_cloudasset=False,
|
||||
incloud=False,
|
||||
not_incloud=False,
|
||||
folder=folder,
|
||||
from_date=from_date,
|
||||
to_date=to_date,
|
||||
from_time=from_time,
|
||||
to_time=to_time,
|
||||
year=year,
|
||||
portrait=portrait,
|
||||
not_portrait=not_portrait,
|
||||
screenshot=screenshot,
|
||||
not_screenshot=not_screenshot,
|
||||
slow_mo=slow_mo,
|
||||
not_slow_mo=not_slow_mo,
|
||||
time_lapse=time_lapse,
|
||||
not_time_lapse=not_time_lapse,
|
||||
hdr=hdr,
|
||||
not_hdr=not_hdr,
|
||||
selfie=selfie,
|
||||
not_selfie=not_selfie,
|
||||
panorama=panorama,
|
||||
not_panorama=not_panorama,
|
||||
has_raw=has_raw,
|
||||
place=place,
|
||||
no_place=no_place,
|
||||
location=location,
|
||||
no_location=no_location,
|
||||
label=label,
|
||||
deleted=deleted,
|
||||
deleted_only=deleted_only,
|
||||
function=query_function,
|
||||
has_comment=has_comment,
|
||||
no_comment=no_comment,
|
||||
has_likes=has_likes,
|
||||
no_likes=no_likes,
|
||||
is_reference=is_reference,
|
||||
has_raw=has_raw,
|
||||
hdr=hdr,
|
||||
hidden=hidden,
|
||||
ignore_case=ignore_case,
|
||||
in_album=in_album,
|
||||
not_in_album=not_in_album,
|
||||
burst_photos=export_bursts,
|
||||
incloud=False,
|
||||
is_reference=is_reference,
|
||||
keyword=keyword,
|
||||
label=label,
|
||||
live=live,
|
||||
location=location,
|
||||
max_size=max_size,
|
||||
min_size=min_size,
|
||||
# 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=missing,
|
||||
movies=movies,
|
||||
name=name,
|
||||
min_size=min_size,
|
||||
max_size=max_size,
|
||||
regex=regex,
|
||||
selected=selected,
|
||||
exif=exif,
|
||||
no_comment=no_comment,
|
||||
no_description=no_description,
|
||||
no_likes=no_likes,
|
||||
no_location=no_location,
|
||||
no_place=no_place,
|
||||
no_title=no_title,
|
||||
not_burst=not_burst,
|
||||
not_cloudasset=False,
|
||||
not_favorite=not_favorite,
|
||||
not_hdr=not_hdr,
|
||||
not_hidden=not_hidden,
|
||||
not_in_album=not_in_album,
|
||||
not_incloud=False,
|
||||
not_live=not_live,
|
||||
not_missing=None,
|
||||
not_panorama=not_panorama,
|
||||
not_portrait=not_portrait,
|
||||
not_screenshot=not_screenshot,
|
||||
not_selfie=not_selfie,
|
||||
not_shared=not_shared,
|
||||
not_slow_mo=not_slow_mo,
|
||||
not_time_lapse=not_time_lapse,
|
||||
panorama=panorama,
|
||||
person=person,
|
||||
photos=photos,
|
||||
place=place,
|
||||
portrait=portrait,
|
||||
query_eval=query_eval,
|
||||
function=query_function,
|
||||
duplicate=duplicate,
|
||||
regex=regex,
|
||||
screenshot=screenshot,
|
||||
selected=selected,
|
||||
selfie=selfie,
|
||||
shared=shared,
|
||||
slow_mo=slow_mo,
|
||||
time_lapse=time_lapse,
|
||||
title=title,
|
||||
to_date=to_date,
|
||||
to_time=to_time,
|
||||
uti=uti,
|
||||
uuid=uuid,
|
||||
year=year,
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -73,83 +73,86 @@ def query(
|
||||
cli_obj,
|
||||
db,
|
||||
photos_library,
|
||||
keyword,
|
||||
person,
|
||||
add_to_album,
|
||||
added_after,
|
||||
added_before,
|
||||
added_in_last,
|
||||
album,
|
||||
folder,
|
||||
name,
|
||||
uuid,
|
||||
uuid_from_file,
|
||||
title,
|
||||
no_title,
|
||||
burst,
|
||||
cloudasset,
|
||||
deleted_only,
|
||||
deleted,
|
||||
description,
|
||||
no_description,
|
||||
ignore_case,
|
||||
json_,
|
||||
duplicate,
|
||||
edited,
|
||||
exif,
|
||||
external_edit,
|
||||
favorite,
|
||||
not_favorite,
|
||||
folder,
|
||||
from_date,
|
||||
from_time,
|
||||
has_comment,
|
||||
has_likes,
|
||||
has_raw,
|
||||
hdr,
|
||||
hidden,
|
||||
not_hidden,
|
||||
ignore_case,
|
||||
in_album,
|
||||
incloud,
|
||||
is_reference,
|
||||
json_,
|
||||
keyword,
|
||||
label,
|
||||
live,
|
||||
location,
|
||||
max_size,
|
||||
min_size,
|
||||
missing,
|
||||
name,
|
||||
no_comment,
|
||||
no_description,
|
||||
no_likes,
|
||||
no_location,
|
||||
no_place,
|
||||
no_title,
|
||||
not_burst,
|
||||
not_cloudasset,
|
||||
not_favorite,
|
||||
not_hdr,
|
||||
not_hidden,
|
||||
not_in_album,
|
||||
not_incloud,
|
||||
not_live,
|
||||
not_missing,
|
||||
shared,
|
||||
not_panorama,
|
||||
not_portrait,
|
||||
not_screenshot,
|
||||
not_selfie,
|
||||
not_shared,
|
||||
not_slow_mo,
|
||||
not_time_lapse,
|
||||
only_movies,
|
||||
only_photos,
|
||||
uti,
|
||||
burst,
|
||||
not_burst,
|
||||
live,
|
||||
not_live,
|
||||
cloudasset,
|
||||
not_cloudasset,
|
||||
incloud,
|
||||
not_incloud,
|
||||
from_date,
|
||||
to_date,
|
||||
from_time,
|
||||
to_time,
|
||||
year,
|
||||
portrait,
|
||||
not_portrait,
|
||||
screenshot,
|
||||
not_screenshot,
|
||||
slow_mo,
|
||||
not_slow_mo,
|
||||
time_lapse,
|
||||
not_time_lapse,
|
||||
hdr,
|
||||
not_hdr,
|
||||
selfie,
|
||||
not_selfie,
|
||||
panorama,
|
||||
not_panorama,
|
||||
has_raw,
|
||||
person,
|
||||
place,
|
||||
no_place,
|
||||
location,
|
||||
no_location,
|
||||
label,
|
||||
deleted,
|
||||
deleted_only,
|
||||
has_comment,
|
||||
no_comment,
|
||||
has_likes,
|
||||
no_likes,
|
||||
is_reference,
|
||||
in_album,
|
||||
not_in_album,
|
||||
duplicate,
|
||||
min_size,
|
||||
max_size,
|
||||
regex,
|
||||
selected,
|
||||
exif,
|
||||
portrait,
|
||||
query_eval,
|
||||
query_function,
|
||||
add_to_album,
|
||||
regex,
|
||||
screenshot,
|
||||
selected,
|
||||
selfie,
|
||||
shared,
|
||||
slow_mo,
|
||||
time_lapse,
|
||||
title,
|
||||
to_date,
|
||||
to_time,
|
||||
uti,
|
||||
uuid_from_file,
|
||||
uuid,
|
||||
year,
|
||||
debug, # handled in cli/__init__.py
|
||||
):
|
||||
"""Query the Photos database using 1 or more search options;
|
||||
@@ -160,58 +163,61 @@ def query(
|
||||
# if no query terms, show help and return
|
||||
# sanity check input args
|
||||
nonexclusive = [
|
||||
keyword,
|
||||
person,
|
||||
added_after,
|
||||
added_before,
|
||||
added_in_last,
|
||||
album,
|
||||
folder,
|
||||
name,
|
||||
uuid,
|
||||
uuid_from_file,
|
||||
duplicate,
|
||||
edited,
|
||||
exif,
|
||||
external_edit,
|
||||
uti,
|
||||
has_raw,
|
||||
folder,
|
||||
from_date,
|
||||
to_date,
|
||||
from_time,
|
||||
to_time,
|
||||
year,
|
||||
label,
|
||||
has_raw,
|
||||
is_reference,
|
||||
keyword,
|
||||
label,
|
||||
max_size,
|
||||
min_size,
|
||||
name,
|
||||
person,
|
||||
query_eval,
|
||||
query_function,
|
||||
min_size,
|
||||
max_size,
|
||||
regex,
|
||||
selected,
|
||||
exif,
|
||||
duplicate,
|
||||
to_date,
|
||||
to_time,
|
||||
uti,
|
||||
uuid_from_file,
|
||||
uuid,
|
||||
year,
|
||||
]
|
||||
exclusive = [
|
||||
(favorite, not_favorite),
|
||||
(hidden, not_hidden),
|
||||
(missing, not_missing),
|
||||
(any(title), no_title),
|
||||
(any(description), no_description),
|
||||
(only_photos, only_movies),
|
||||
(burst, not_burst),
|
||||
(live, not_live),
|
||||
(cloudasset, not_cloudasset),
|
||||
(incloud, not_incloud),
|
||||
(portrait, not_portrait),
|
||||
(screenshot, not_screenshot),
|
||||
(slow_mo, not_slow_mo),
|
||||
(time_lapse, not_time_lapse),
|
||||
(hdr, not_hdr),
|
||||
(selfie, not_selfie),
|
||||
(panorama, not_panorama),
|
||||
(any(place), no_place),
|
||||
(any(title), no_title),
|
||||
(burst, not_burst),
|
||||
(cloudasset, not_cloudasset),
|
||||
(deleted, deleted_only),
|
||||
(shared, not_shared),
|
||||
(favorite, not_favorite),
|
||||
(has_comment, no_comment),
|
||||
(has_likes, no_likes),
|
||||
(hdr, not_hdr),
|
||||
(hidden, not_hidden),
|
||||
(in_album, not_in_album),
|
||||
(incloud, not_incloud),
|
||||
(live, not_live),
|
||||
(location, no_location),
|
||||
(missing, not_missing),
|
||||
(only_photos, only_movies),
|
||||
(panorama, not_panorama),
|
||||
(portrait, not_portrait),
|
||||
(screenshot, not_screenshot),
|
||||
(selfie, not_selfie),
|
||||
(shared, not_shared),
|
||||
(slow_mo, not_slow_mo),
|
||||
(time_lapse, not_time_lapse),
|
||||
]
|
||||
# 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(
|
||||
@@ -247,80 +253,83 @@ def query(
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=db)
|
||||
query_options = QueryOptions(
|
||||
keyword=keyword,
|
||||
person=person,
|
||||
added_after=added_after,
|
||||
added_before=added_before,
|
||||
added_in_last=added_in_last,
|
||||
album=album,
|
||||
folder=folder,
|
||||
uuid=uuid,
|
||||
title=title,
|
||||
no_title=no_title,
|
||||
burst=burst,
|
||||
cloudasset=cloudasset,
|
||||
deleted_only=deleted_only,
|
||||
deleted=deleted,
|
||||
description=description,
|
||||
no_description=no_description,
|
||||
ignore_case=ignore_case,
|
||||
duplicate=duplicate,
|
||||
edited=edited,
|
||||
exif=exif,
|
||||
external_edit=external_edit,
|
||||
favorite=favorite,
|
||||
not_favorite=not_favorite,
|
||||
hidden=hidden,
|
||||
not_hidden=not_hidden,
|
||||
missing=missing,
|
||||
not_missing=not_missing,
|
||||
shared=shared,
|
||||
not_shared=not_shared,
|
||||
photos=photos,
|
||||
movies=movies,
|
||||
uti=uti,
|
||||
burst=burst,
|
||||
not_burst=not_burst,
|
||||
live=live,
|
||||
not_live=not_live,
|
||||
cloudasset=cloudasset,
|
||||
not_cloudasset=not_cloudasset,
|
||||
incloud=incloud,
|
||||
not_incloud=not_incloud,
|
||||
folder=folder,
|
||||
from_date=from_date,
|
||||
to_date=to_date,
|
||||
from_time=from_time,
|
||||
to_time=to_time,
|
||||
year=year,
|
||||
portrait=portrait,
|
||||
not_portrait=not_portrait,
|
||||
screenshot=screenshot,
|
||||
not_screenshot=not_screenshot,
|
||||
slow_mo=slow_mo,
|
||||
not_slow_mo=not_slow_mo,
|
||||
time_lapse=time_lapse,
|
||||
not_time_lapse=not_time_lapse,
|
||||
hdr=hdr,
|
||||
not_hdr=not_hdr,
|
||||
selfie=selfie,
|
||||
not_selfie=not_selfie,
|
||||
panorama=panorama,
|
||||
not_panorama=not_panorama,
|
||||
has_raw=has_raw,
|
||||
place=place,
|
||||
no_place=no_place,
|
||||
location=location,
|
||||
no_location=no_location,
|
||||
label=label,
|
||||
deleted=deleted,
|
||||
deleted_only=deleted_only,
|
||||
has_comment=has_comment,
|
||||
no_comment=no_comment,
|
||||
has_likes=has_likes,
|
||||
no_likes=no_likes,
|
||||
is_reference=is_reference,
|
||||
in_album=in_album,
|
||||
not_in_album=not_in_album,
|
||||
name=name,
|
||||
min_size=min_size,
|
||||
max_size=max_size,
|
||||
query_eval=query_eval,
|
||||
function=query_function,
|
||||
has_comment=has_comment,
|
||||
has_likes=has_likes,
|
||||
has_raw=has_raw,
|
||||
hdr=hdr,
|
||||
hidden=hidden,
|
||||
ignore_case=ignore_case,
|
||||
in_album=in_album,
|
||||
incloud=incloud,
|
||||
is_reference=is_reference,
|
||||
keyword=keyword,
|
||||
label=label,
|
||||
live=live,
|
||||
location=location,
|
||||
max_size=max_size,
|
||||
min_size=min_size,
|
||||
missing=missing,
|
||||
movies=movies,
|
||||
name=name,
|
||||
no_comment=no_comment,
|
||||
no_description=no_description,
|
||||
no_likes=no_likes,
|
||||
no_location=no_location,
|
||||
no_place=no_place,
|
||||
no_title=no_title,
|
||||
not_burst=not_burst,
|
||||
not_cloudasset=not_cloudasset,
|
||||
not_favorite=not_favorite,
|
||||
not_hdr=not_hdr,
|
||||
not_hidden=not_hidden,
|
||||
not_in_album=not_in_album,
|
||||
not_incloud=not_incloud,
|
||||
not_live=not_live,
|
||||
not_missing=not_missing,
|
||||
not_panorama=not_panorama,
|
||||
not_portrait=not_portrait,
|
||||
not_screenshot=not_screenshot,
|
||||
not_selfie=not_selfie,
|
||||
not_shared=not_shared,
|
||||
not_slow_mo=not_slow_mo,
|
||||
not_time_lapse=not_time_lapse,
|
||||
panorama=panorama,
|
||||
person=person,
|
||||
photos=photos,
|
||||
place=place,
|
||||
portrait=portrait,
|
||||
query_eval=query_eval,
|
||||
regex=regex,
|
||||
screenshot=screenshot,
|
||||
selected=selected,
|
||||
exif=exif,
|
||||
duplicate=duplicate,
|
||||
selfie=selfie,
|
||||
shared=shared,
|
||||
slow_mo=slow_mo,
|
||||
time_lapse=time_lapse,
|
||||
title=title,
|
||||
to_date=to_date,
|
||||
to_time=to_time,
|
||||
uti=uti,
|
||||
uuid=uuid,
|
||||
year=year,
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -241,55 +241,58 @@ def _query_options_from_kwargs(**kwargs) -> QueryOptions:
|
||||
"""Validate query options and create a QueryOptions instance"""
|
||||
# sanity check input args
|
||||
nonexclusive = [
|
||||
"keyword",
|
||||
"person",
|
||||
"added_after",
|
||||
"added_before",
|
||||
"added_in_last",
|
||||
"album",
|
||||
"folder",
|
||||
"name",
|
||||
"uuid",
|
||||
"uuid_from_file",
|
||||
"duplicate",
|
||||
"edited",
|
||||
"exif",
|
||||
"external_edit",
|
||||
"uti",
|
||||
"has_raw",
|
||||
"folder",
|
||||
"from_date",
|
||||
"to_date",
|
||||
"from_time",
|
||||
"to_time",
|
||||
"year",
|
||||
"label",
|
||||
"has_raw",
|
||||
"is_reference",
|
||||
"keyword",
|
||||
"label",
|
||||
"max_size",
|
||||
"min_size",
|
||||
"name",
|
||||
"person",
|
||||
"query_eval",
|
||||
"query_function",
|
||||
"min_size",
|
||||
"max_size",
|
||||
"regex",
|
||||
"selected",
|
||||
"exif",
|
||||
"duplicate",
|
||||
"to_date",
|
||||
"to_time",
|
||||
"uti",
|
||||
"uuid_from_file",
|
||||
"uuid",
|
||||
"year",
|
||||
]
|
||||
exclusive = [
|
||||
("favorite", "not_favorite"),
|
||||
("hidden", "not_hidden"),
|
||||
("missing", "not_missing"),
|
||||
("only_photos", "only_movies"),
|
||||
("burst", "not_burst"),
|
||||
("live", "not_live"),
|
||||
("cloudasset", "not_cloudasset"),
|
||||
("incloud", "not_incloud"),
|
||||
("portrait", "not_portrait"),
|
||||
("screenshot", "not_screenshot"),
|
||||
("slow_mo", "not_slow_mo"),
|
||||
("time_lapse", "not_time_lapse"),
|
||||
("hdr", "not_hdr"),
|
||||
("selfie", "not_selfie"),
|
||||
("panorama", "not_panorama"),
|
||||
("deleted", "deleted_only"),
|
||||
("shared", "not_shared"),
|
||||
("favorite", "not_favorite"),
|
||||
("has_comment", "no_comment"),
|
||||
("has_likes", "no_likes"),
|
||||
("hdr", "not_hdr"),
|
||||
("hidden", "not_hidden"),
|
||||
("in_album", "not_in_album"),
|
||||
("incloud", "not_incloud"),
|
||||
("live", "not_live"),
|
||||
("location", "no_location"),
|
||||
("missing", "not_missing"),
|
||||
("only_photos", "only_movies"),
|
||||
("panorama", "not_panorama"),
|
||||
("portrait", "not_portrait"),
|
||||
("screenshot", "not_screenshot"),
|
||||
("selfie", "not_selfie"),
|
||||
("shared", "not_shared"),
|
||||
("slow_mo", "not_slow_mo"),
|
||||
("time_lapse", "not_time_lapse"),
|
||||
]
|
||||
# print help if no non-exclusive term or a double exclusive term is given
|
||||
# TODO: add option to validate requiring at least one query arg
|
||||
|
||||
@@ -3446,6 +3446,23 @@ class PhotosDB:
|
||||
matching_photos.append(p)
|
||||
photos = matching_photos
|
||||
|
||||
if options.added_after:
|
||||
added_after = options.added_after
|
||||
if not datetime_has_tz(added_after):
|
||||
added_after = datetime_naive_to_local(added_after)
|
||||
photos = [p for p in photos if p.date_added and p.date_added > added_after]
|
||||
|
||||
if options.added_before:
|
||||
added_before = options.added_before
|
||||
if not datetime_has_tz(added_before):
|
||||
added_before = datetime_naive_to_local(added_before)
|
||||
photos = [p for p in photos if p.date_added and p.date_added < added_before]
|
||||
|
||||
if options.added_in_last:
|
||||
added_after = datetime.now() - options.added_in_last
|
||||
added_after = datetime_naive_to_local(added_after)
|
||||
photos = [p for p in photos if p.date_added and p.date_added > added_after]
|
||||
|
||||
if options.function:
|
||||
for function in options.function:
|
||||
photos = function[0](photos)
|
||||
|
||||
@@ -15,158 +15,163 @@ class QueryOptions:
|
||||
"""QueryOptions class for PhotosDB.query
|
||||
|
||||
Attributes:
|
||||
keyword: list of keywords to search for
|
||||
person: list of person names to search for
|
||||
added_after: search for photos added after a given date
|
||||
added_before: search for photos added before a given date
|
||||
added_in_last: search for photos added in last X datetime.timedelta
|
||||
album: list of album names to search for
|
||||
folder: list of folder names to search for
|
||||
uuid: list of uuids to search for
|
||||
title: list of titles to search for
|
||||
no_title: search for photos with no title
|
||||
burst_photos: search for burst photos
|
||||
burst: search for burst photos
|
||||
cloudasset: search for photos that are managed by iCloud
|
||||
deleted_only: search only for deleted photos
|
||||
deleted: also include deleted photos
|
||||
description: list of descriptions to search for
|
||||
no_description: search for photos with no description
|
||||
ignore_case: ignore case when searching
|
||||
duplicate: search for duplicate photos
|
||||
edited: search for edited photos
|
||||
exif: search for photos with EXIF tags that matches the given data
|
||||
external_edit: search for photos edited in external apps
|
||||
favorite: search for favorite photos
|
||||
not_favorite: search for non-favorite photos
|
||||
hidden: search for hidden photos
|
||||
not_hidden: search for non-hidden photos
|
||||
missing: search for missing photos
|
||||
not_missing: search for non-missing photos
|
||||
shared: search for shared photos
|
||||
not_shared: search for non-shared photos
|
||||
photos: search for photos
|
||||
movies: search for movies
|
||||
uti: list of UTIs to search for
|
||||
burst: search for burst photos
|
||||
not_burst: search for non-burst photos
|
||||
live: search for live photos
|
||||
not_live: search for non-live photos
|
||||
cloudasset: search for photos that are managed by iCloud
|
||||
not_cloudasset: search for photos that are not managed by iCloud
|
||||
incloud: search for cloud assets that are synched to iCloud
|
||||
not_incloud: search for cloud asset photos that are not yet synched to iCloud
|
||||
folder: list of folder names to search for
|
||||
from_date: search for photos taken on or after this date
|
||||
to_date: search for photos taken on or before this date
|
||||
portrait: search for portrait photos
|
||||
not_portrait: search for non-portrait photos
|
||||
screenshot: search for screenshot photos
|
||||
not_screenshot: search for non-screenshot photos
|
||||
slow_mo: search for slow-mo photos
|
||||
not_slow_mo: search for non-slow-mo photos
|
||||
time_lapse: search for time-lapse photos
|
||||
not_time_lapse: search for non-time-lapse photos
|
||||
hdr: search for HDR photos
|
||||
not_hdr: search for non-HDR photos
|
||||
selfie: search for selfie photos
|
||||
not_selfie: search for non-selfie photos
|
||||
panorama: search for panorama photos
|
||||
not_panorama: search for non-panorama photos
|
||||
has_raw: search for photos with associated raw files
|
||||
place: list of place names to search for
|
||||
no_place: search for photos with no place
|
||||
label: list of labels to search for
|
||||
deleted: also include deleted photos
|
||||
deleted_only: search only for deleted photos
|
||||
has_comment: search for photos with comments
|
||||
no_comment: search for photos with no comments
|
||||
has_likes: search for shared photos with likes
|
||||
no_likes: search for shared photos with no likes
|
||||
is_reference: search for photos stored by reference (that is, they are not managed by Photos)
|
||||
in_album: search for photos in an album
|
||||
not_in_album: search for photos not in an album
|
||||
burst_photos: search for burst photos
|
||||
missing_bursts: for burst photos, also include burst photos that are missing
|
||||
name: list of names to search for
|
||||
min_size: minimum size of photos to search for
|
||||
max_size: maximum size of photos to search for
|
||||
regex: list of regular expressions to search for
|
||||
query_eval: list of query expressions to evaluate
|
||||
duplicate: search for duplicate photos
|
||||
location: search for photos with a location
|
||||
no_location: search for photos with no location
|
||||
function: list of query functions to evaluate
|
||||
has_comment: search for photos with comments
|
||||
has_likes: search for shared photos with likes
|
||||
has_raw: search for photos with associated raw files
|
||||
hdr: search for HDR photos
|
||||
hidden: search for hidden photos
|
||||
ignore_case: ignore case when searching
|
||||
in_album: search for photos in an album
|
||||
incloud: search for cloud assets that are synched to iCloud
|
||||
is_reference: search for photos stored by reference (that is, they are not managed by Photos)
|
||||
keyword: list of keywords to search for
|
||||
label: list of labels to search for
|
||||
live: search for live photos
|
||||
location: search for photos with a location
|
||||
max_size: maximum size of photos to search for
|
||||
min_size: minimum size of photos to search for
|
||||
missing_bursts: for burst photos, also include burst photos that are missing
|
||||
missing: search for missing photos
|
||||
movies: search for movies
|
||||
name: list of names to search for
|
||||
no_comment: search for photos with no comments
|
||||
no_description: search for photos with no description
|
||||
no_likes: search for shared photos with no likes
|
||||
no_location: search for photos with no location
|
||||
no_place: search for photos with no place
|
||||
no_title: search for photos with no title
|
||||
not_burst: search for non-burst photos
|
||||
not_cloudasset: search for photos that are not managed by iCloud
|
||||
not_favorite: search for non-favorite photos
|
||||
not_hdr: search for non-HDR photos
|
||||
not_hidden: search for non-hidden photos
|
||||
not_in_album: search for photos not in an album
|
||||
not_incloud: search for cloud asset photos that are not yet synched to iCloud
|
||||
not_live: search for non-live photos
|
||||
not_missing: search for non-missing photos
|
||||
not_panorama: search for non-panorama photos
|
||||
not_portrait: search for non-portrait photos
|
||||
not_screenshot: search for non-screenshot photos
|
||||
not_selfie: search for non-selfie photos
|
||||
not_shared: search for non-shared photos
|
||||
not_slow_mo: search for non-slow-mo photos
|
||||
not_time_lapse: search for non-time-lapse photos
|
||||
panorama: search for panorama photos
|
||||
person: list of person names to search for
|
||||
photos: search for photos
|
||||
place: list of place names to search for
|
||||
portrait: search for portrait photos
|
||||
query_eval: list of query expressions to evaluate
|
||||
regex: list of regular expressions to search for
|
||||
screenshot: search for screenshot photos
|
||||
selected: search for selected photos
|
||||
exif: search for photos with EXIF tags that matches the given data
|
||||
selfie: search for selfie photos
|
||||
shared: search for shared photos
|
||||
slow_mo: search for slow-mo photos
|
||||
time_lapse: search for time-lapse photos
|
||||
title: list of titles to search for
|
||||
to_date: search for photos taken on or before this date
|
||||
uti: list of UTIs to search for
|
||||
uuid: list of uuids to search for
|
||||
year: search for photos taken in a given year
|
||||
|
||||
"""
|
||||
|
||||
keyword: Optional[Iterable[str]] = None
|
||||
person: Optional[Iterable[str]] = None
|
||||
added_after: Optional[datetime.datetime] = None
|
||||
added_before: Optional[datetime.datetime] = None
|
||||
added_in_last: Optional[datetime.timedelta] = None
|
||||
album: Optional[Iterable[str]] = None
|
||||
folder: Optional[Iterable[str]] = None
|
||||
uuid: Optional[Iterable[str]] = None
|
||||
title: Optional[Iterable[str]] = None
|
||||
no_title: Optional[bool] = None
|
||||
burst_photos: Optional[bool] = None
|
||||
burst: Optional[bool] = None
|
||||
cloudasset: Optional[bool] = None
|
||||
deleted_only: Optional[bool] = None
|
||||
deleted: Optional[bool] = None
|
||||
description: Optional[Iterable[str]] = None
|
||||
no_description: Optional[bool] = None
|
||||
ignore_case: Optional[bool] = None
|
||||
duplicate: Optional[bool] = None
|
||||
edited: Optional[bool] = None
|
||||
exif: Optional[Iterable[Tuple[str, str]]] = None
|
||||
external_edit: Optional[bool] = None
|
||||
favorite: Optional[bool] = None
|
||||
not_favorite: Optional[bool] = None
|
||||
hidden: Optional[bool] = None
|
||||
not_hidden: Optional[bool] = None
|
||||
missing: Optional[bool] = None
|
||||
not_missing: Optional[bool] = None
|
||||
shared: Optional[bool] = None
|
||||
not_shared: Optional[bool] = None
|
||||
photos: Optional[bool] = True
|
||||
movies: Optional[bool] = True
|
||||
uti: Optional[Iterable[str]] = None
|
||||
burst: Optional[bool] = None
|
||||
not_burst: Optional[bool] = None
|
||||
live: Optional[bool] = None
|
||||
not_live: Optional[bool] = None
|
||||
cloudasset: Optional[bool] = None
|
||||
not_cloudasset: Optional[bool] = None
|
||||
incloud: Optional[bool] = None
|
||||
not_incloud: Optional[bool] = None
|
||||
folder: Optional[Iterable[str]] = None
|
||||
from_date: Optional[datetime.datetime] = None
|
||||
to_date: Optional[datetime.datetime] = None
|
||||
from_time: Optional[datetime.time] = None
|
||||
to_time: Optional[datetime.time] = None
|
||||
portrait: Optional[bool] = None
|
||||
not_portrait: Optional[bool] = None
|
||||
screenshot: Optional[bool] = None
|
||||
not_screenshot: Optional[bool] = None
|
||||
slow_mo: Optional[bool] = None
|
||||
not_slow_mo: Optional[bool] = None
|
||||
time_lapse: Optional[bool] = None
|
||||
not_time_lapse: Optional[bool] = None
|
||||
hdr: Optional[bool] = None
|
||||
not_hdr: Optional[bool] = None
|
||||
selfie: Optional[bool] = None
|
||||
not_selfie: Optional[bool] = None
|
||||
panorama: Optional[bool] = None
|
||||
not_panorama: Optional[bool] = None
|
||||
has_raw: Optional[bool] = None
|
||||
place: Optional[Iterable[str]] = None
|
||||
no_place: Optional[bool] = None
|
||||
label: Optional[Iterable[str]] = None
|
||||
deleted: Optional[bool] = None
|
||||
deleted_only: Optional[bool] = None
|
||||
has_comment: Optional[bool] = None
|
||||
no_comment: Optional[bool] = None
|
||||
has_likes: Optional[bool] = None
|
||||
no_likes: Optional[bool] = None
|
||||
is_reference: Optional[bool] = None
|
||||
in_album: Optional[bool] = None
|
||||
not_in_album: Optional[bool] = None
|
||||
burst_photos: Optional[bool] = None
|
||||
missing_bursts: Optional[bool] = None
|
||||
name: Optional[Iterable[str]] = None
|
||||
min_size: Optional[bitmath.Byte] = None
|
||||
max_size: Optional[bitmath.Byte] = None
|
||||
regex: Optional[Iterable[Tuple[str, str]]] = None
|
||||
query_eval: Optional[Iterable[str]] = None
|
||||
duplicate: Optional[bool] = None
|
||||
location: Optional[bool] = None
|
||||
no_location: Optional[bool] = None
|
||||
function: Optional[List[Tuple[callable, str]]] = None
|
||||
has_comment: Optional[bool] = None
|
||||
has_likes: Optional[bool] = None
|
||||
has_raw: Optional[bool] = None
|
||||
hdr: Optional[bool] = None
|
||||
hidden: Optional[bool] = None
|
||||
ignore_case: Optional[bool] = None
|
||||
in_album: Optional[bool] = None
|
||||
incloud: Optional[bool] = None
|
||||
is_reference: Optional[bool] = None
|
||||
keyword: Optional[Iterable[str]] = None
|
||||
label: Optional[Iterable[str]] = None
|
||||
live: Optional[bool] = None
|
||||
location: Optional[bool] = None
|
||||
max_size: Optional[bitmath.Byte] = None
|
||||
min_size: Optional[bitmath.Byte] = None
|
||||
missing_bursts: Optional[bool] = None
|
||||
missing: Optional[bool] = None
|
||||
movies: Optional[bool] = True
|
||||
name: Optional[Iterable[str]] = None
|
||||
no_comment: Optional[bool] = None
|
||||
no_description: Optional[bool] = None
|
||||
no_likes: Optional[bool] = None
|
||||
no_location: Optional[bool] = None
|
||||
no_place: Optional[bool] = None
|
||||
no_title: Optional[bool] = None
|
||||
not_burst: Optional[bool] = None
|
||||
not_cloudasset: Optional[bool] = None
|
||||
not_favorite: Optional[bool] = None
|
||||
not_hdr: Optional[bool] = None
|
||||
not_hidden: Optional[bool] = None
|
||||
not_in_album: Optional[bool] = None
|
||||
not_incloud: Optional[bool] = None
|
||||
not_live: Optional[bool] = None
|
||||
not_missing: Optional[bool] = None
|
||||
not_panorama: Optional[bool] = None
|
||||
not_portrait: Optional[bool] = None
|
||||
not_screenshot: Optional[bool] = None
|
||||
not_selfie: Optional[bool] = None
|
||||
not_shared: Optional[bool] = None
|
||||
not_slow_mo: Optional[bool] = None
|
||||
not_time_lapse: Optional[bool] = None
|
||||
panorama: Optional[bool] = None
|
||||
person: Optional[Iterable[str]] = None
|
||||
photos: Optional[bool] = True
|
||||
place: Optional[Iterable[str]] = None
|
||||
portrait: Optional[bool] = None
|
||||
query_eval: Optional[Iterable[str]] = None
|
||||
regex: Optional[Iterable[Tuple[str, str]]] = None
|
||||
screenshot: Optional[bool] = None
|
||||
selected: Optional[bool] = None
|
||||
exif: Optional[Iterable[Tuple[str, str]]] = None
|
||||
selfie: Optional[bool] = None
|
||||
shared: Optional[bool] = None
|
||||
slow_mo: Optional[bool] = None
|
||||
time_lapse: Optional[bool] = None
|
||||
title: Optional[Iterable[str]] = None
|
||||
to_date: Optional[datetime.datetime] = None
|
||||
to_time: Optional[datetime.time] = None
|
||||
uti: Optional[Iterable[str]] = None
|
||||
uuid: Optional[Iterable[str]] = None
|
||||
year: Optional[Iterable[int]] = None
|
||||
|
||||
def asdict(self):
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
""" Test the command line interface (CLI) """
|
||||
|
||||
import datetime
|
||||
import glob
|
||||
import json
|
||||
@@ -7079,6 +7078,46 @@ def test_query_function():
|
||||
assert json_got[0]["original_filename"] == "DSC03584.dng"
|
||||
|
||||
|
||||
def test_query_added_after():
|
||||
"""test query --added-after"""
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
# pylint: disable=not-context-manager
|
||||
results = runner.invoke(
|
||||
query,
|
||||
[
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
"--json",
|
||||
"--added-after",
|
||||
"2022-02-03",
|
||||
],
|
||||
)
|
||||
assert results.exit_code == 0
|
||||
json_got = json.loads(results.output)
|
||||
assert len(json_got) == 4
|
||||
|
||||
|
||||
def test_query_added_before():
|
||||
"""test query --added-before"""
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
# pylint: disable=not-context-manager
|
||||
results = runner.invoke(
|
||||
query,
|
||||
[
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
"--json",
|
||||
"--added-before",
|
||||
"2019-07-28",
|
||||
],
|
||||
)
|
||||
assert results.exit_code == 0
|
||||
json_got = json.loads(results.output)
|
||||
assert len(json_got) == 7
|
||||
|
||||
|
||||
def test_export_export_dir_template():
|
||||
"""Test {export_dir} template"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user