Added batch_edit.py example, [skip ci]

This commit is contained in:
Rhet Turnbull
2023-02-21 21:16:53 -08:00
parent e89f8a14b4
commit 3a77a3e5f0

View File

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