Added --added-after, --added-before, --added-in-last, #439 (#683)

This commit is contained in:
Rhet Turnbull
2022-05-05 17:06:55 -07:00
committed by GitHub
parent 3ed658a7d0
commit 4533057142
7 changed files with 641 additions and 535 deletions

View File

@@ -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,
)

View File

@@ -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:

View File

@@ -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:

View File

@@ -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

View File

@@ -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)

View File

@@ -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):

View File

@@ -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"""