Added batch_edit.py example, [skip ci]
This commit is contained in:
@@ -6,6 +6,7 @@ Run this with `osxphotos run batch_edit.py` or `osxphotos run batch_edit.py --he
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import functools
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import click
|
import click
|
||||||
@@ -76,47 +77,89 @@ def batch_edit(
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
echo(f"Processing [num]{len(photos)}[/] photos...")
|
echo(f"Processing [num]{len(photos)}[/] photos...")
|
||||||
|
# sort photos by date so that {counter} order is correct
|
||||||
|
photos.sort(key=lambda p: p.date)
|
||||||
for photo in photos:
|
for photo in photos:
|
||||||
ps_photo = photoscript.Photo(photo.uuid)
|
|
||||||
# don't render None values
|
|
||||||
render_options = RenderOptions(none_str="")
|
|
||||||
verbose(
|
verbose(
|
||||||
f"Processing [filename]{photo.original_filename}[/] ([uuid]{photo.uuid}[/])"
|
f"Processing [filename]{photo.original_filename}[/] ([uuid]{photo.uuid}[/])"
|
||||||
)
|
)
|
||||||
if title:
|
set_photo_title_from_template(photo, title, dry_run)
|
||||||
title_string, _ = photo.render_template(title, render_options)
|
set_photo_description_from_template(photo, description, dry_run)
|
||||||
if len(title_string) > 1:
|
set_photo_keywords_from_template(photo, keyword, dry_run)
|
||||||
echo_error(
|
|
||||||
f"[error] Title template must return a single string: {title_string}"
|
|
||||||
)
|
def set_photo_title_from_template(
|
||||||
sys.exit(1)
|
photo: osxphotos.PhotoInfo, title_template: str, dry_run: bool
|
||||||
if title_string:
|
):
|
||||||
verbose(f"Setting title to [bold]{title_string[0]}")
|
"""Set photo title from template"""
|
||||||
if not dry_run:
|
if not title_template:
|
||||||
ps_photo.title = title_string[0]
|
return
|
||||||
if description:
|
|
||||||
description_string, _ = photo.render_template(description, render_options)
|
# don't render None values
|
||||||
if len(description_string) > 1:
|
render_options = RenderOptions(none_str="")
|
||||||
echo_error(
|
|
||||||
f"[error] Description template must return a single string: {description_string}"
|
title_string, _ = photo.render_template(title_template, render_options)
|
||||||
)
|
if len(title_string) > 1:
|
||||||
sys.exit(1)
|
echo_error(
|
||||||
if description_string:
|
f"[error] Title template must return a single string: {title_string}"
|
||||||
verbose(f"Setting description to [bold]{description_string[0]}")
|
)
|
||||||
if not dry_run:
|
sys.exit(1)
|
||||||
ps_photo.description = description_string[0]
|
if title_string:
|
||||||
if keyword:
|
verbose(f"Setting title to [bold]{title_string[0]}")
|
||||||
keywords = set()
|
if not dry_run:
|
||||||
for kw in keyword:
|
ps_photo = photoscript_photo(photo)
|
||||||
kw_string, _ = photo.render_template(kw, render_options)
|
ps_photo.title = title_string[0]
|
||||||
if kw_string:
|
|
||||||
# filter out empty strings
|
|
||||||
keywords.update([k for k in kw_string if k])
|
def set_photo_description_from_template(
|
||||||
verbose(
|
photo: osxphotos.PhotoInfo, description_template: str, dry_run: bool
|
||||||
f"Setting keywords to {', '.join(f'[bold]{kw}[/]' for kw in keywords)}"
|
):
|
||||||
)
|
"""Set photo description from template"""
|
||||||
if not dry_run:
|
if not description_template:
|
||||||
ps_photo.keywords = keywords
|
return
|
||||||
|
|
||||||
|
# don't render None values
|
||||||
|
render_options = RenderOptions(none_str="")
|
||||||
|
|
||||||
|
description_string, _ = photo.render_template(description_template, render_options)
|
||||||
|
if len(description_string) > 1:
|
||||||
|
echo_error(
|
||||||
|
f"[error] Description template must return a single string: {description_string}"
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
if description_string:
|
||||||
|
verbose(f"Setting description to [bold]{description_string[0]}")
|
||||||
|
if not dry_run:
|
||||||
|
ps_photo = photoscript_photo(photo)
|
||||||
|
ps_photo.description = description_string[0]
|
||||||
|
|
||||||
|
|
||||||
|
def set_photo_keywords_from_template(
|
||||||
|
photo: osxphotos.PhotoInfo, keyword_template: list[str], dry_run: bool
|
||||||
|
):
|
||||||
|
"""Set photo keywords from template"""
|
||||||
|
if not keyword_template:
|
||||||
|
return
|
||||||
|
|
||||||
|
# don't render None values
|
||||||
|
render_options = RenderOptions(none_str="")
|
||||||
|
|
||||||
|
keywords = set()
|
||||||
|
for kw in keyword_template:
|
||||||
|
kw_string, _ = photo.render_template(kw, render_options)
|
||||||
|
if kw_string:
|
||||||
|
# filter out empty strings
|
||||||
|
keywords.update([k for k in kw_string if k])
|
||||||
|
verbose(f"Setting keywords to {', '.join(f'[bold]{kw}[/]' for kw in keywords)}")
|
||||||
|
if not dry_run:
|
||||||
|
ps_photo = photoscript_photo(photo)
|
||||||
|
ps_photo.keywords = list(keywords)
|
||||||
|
|
||||||
|
|
||||||
|
@functools.lru_cache(maxsize=128)
|
||||||
|
def photoscript_photo(photo: osxphotos.PhotoInfo) -> photoscript.Photo:
|
||||||
|
"""Return photoscript Photo object for photo"""
|
||||||
|
return photoscript.Photo(photo.uuid)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user