Added batch_edit.py example, [skip ci]
This commit is contained in:
parent
8fdecd56f5
commit
1e10df26c9
@ -18,6 +18,38 @@ from osxphotos.cli.param_types import TemplateString
|
|||||||
from osxphotos.phototemplate import RenderOptions
|
from osxphotos.phototemplate import RenderOptions
|
||||||
|
|
||||||
|
|
||||||
|
class Latitude(click.ParamType):
|
||||||
|
|
||||||
|
name = "Latitude"
|
||||||
|
|
||||||
|
def convert(self, value, param, ctx):
|
||||||
|
try:
|
||||||
|
latitude = float(value)
|
||||||
|
if latitude < -90 or latitude > 90:
|
||||||
|
raise ValueError
|
||||||
|
return latitude
|
||||||
|
except Exception:
|
||||||
|
self.fail(
|
||||||
|
f"Invalid latitude {value}. Must be a floating point number between -90 and 90."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Longitude(click.ParamType):
|
||||||
|
|
||||||
|
name = "Longitude"
|
||||||
|
|
||||||
|
def convert(self, value, param, ctx):
|
||||||
|
try:
|
||||||
|
longitude = float(value)
|
||||||
|
if longitude < -180 or longitude > 180:
|
||||||
|
raise ValueError
|
||||||
|
return longitude
|
||||||
|
except Exception:
|
||||||
|
self.fail(
|
||||||
|
f"Invalid longitude {value}. Must be a floating point number between -180 and 180."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@selection_command(name="batch-edit")
|
@selection_command(name="batch-edit")
|
||||||
@click.option(
|
@click.option(
|
||||||
"--title",
|
"--title",
|
||||||
@ -38,9 +70,22 @@ from osxphotos.phototemplate import RenderOptions
|
|||||||
multiple=True,
|
multiple=True,
|
||||||
help="Set keywords of photo. May be specified multiple times.",
|
help="Set keywords of photo. May be specified multiple times.",
|
||||||
)
|
)
|
||||||
|
@click.option(
|
||||||
|
"--location",
|
||||||
|
metavar="LATITUDE LONGITUDE",
|
||||||
|
type=click.Tuple([Latitude(), Longitude()]),
|
||||||
|
help="Set location of photo. "
|
||||||
|
"Must be specified as a pair of numbers with latitude in the range -90 to 90 and longitude in the range -180 to 180.",
|
||||||
|
)
|
||||||
@click.option("--dry-run", is_flag=True, help="Don't actually change anything.")
|
@click.option("--dry-run", is_flag=True, help="Don't actually change anything.")
|
||||||
def batch_edit(
|
def batch_edit(
|
||||||
photos: list[osxphotos.PhotoInfo], title, description, keyword, dry_run, **kwargs
|
photos: list[osxphotos.PhotoInfo],
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
keyword,
|
||||||
|
location,
|
||||||
|
dry_run,
|
||||||
|
**kwargs,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Batch edit photo metadata such as title, description, keywords, etc.
|
Batch edit photo metadata such as title, description, keywords, etc.
|
||||||
@ -86,6 +131,16 @@ def batch_edit(
|
|||||||
set_photo_title_from_template(photo, title, dry_run)
|
set_photo_title_from_template(photo, title, dry_run)
|
||||||
set_photo_description_from_template(photo, description, dry_run)
|
set_photo_description_from_template(photo, description, dry_run)
|
||||||
set_photo_keywords_from_template(photo, keyword, dry_run)
|
set_photo_keywords_from_template(photo, keyword, dry_run)
|
||||||
|
set_photo_location(photo, location, dry_run)
|
||||||
|
|
||||||
|
|
||||||
|
# cache photoscript Photo object to avoid re-creating it for each photo
|
||||||
|
# maxsize=1 as this function is called repeatedly for each photo then
|
||||||
|
# the next photo is processed
|
||||||
|
@functools.lru_cache(maxsize=1)
|
||||||
|
def photoscript_photo(photo: osxphotos.PhotoInfo) -> photoscript.Photo:
|
||||||
|
"""Return photoscript Photo object for photo"""
|
||||||
|
return photoscript.Photo(photo.uuid)
|
||||||
|
|
||||||
|
|
||||||
def set_photo_title_from_template(
|
def set_photo_title_from_template(
|
||||||
@ -179,13 +234,20 @@ def set_photo_keywords_from_template(
|
|||||||
ps_photo.keywords = list(keywords)
|
ps_photo.keywords = list(keywords)
|
||||||
|
|
||||||
|
|
||||||
# cache photoscript Photo object to avoid re-creating it for each photo
|
def set_photo_location(
|
||||||
# maxsize=1 as this function is called repeatedly for each photo then
|
photo: osxphotos.PhotoInfo, location: tuple[float, float], dry_run: bool
|
||||||
# the next photo is processed
|
):
|
||||||
@functools.lru_cache(maxsize=1)
|
"""Set photo location"""
|
||||||
def photoscript_photo(photo: osxphotos.PhotoInfo) -> photoscript.Photo:
|
if not location or location[0] is None or location[1] is None:
|
||||||
"""Return photoscript Photo object for photo"""
|
return
|
||||||
return photoscript.Photo(photo.uuid)
|
|
||||||
|
latitude, longitude = location
|
||||||
|
verbose(
|
||||||
|
f"Setting [i]location[/] to [num]{latitude:.6f}[/], [num]{longitude:.6f}[/]"
|
||||||
|
)
|
||||||
|
if not dry_run:
|
||||||
|
ps_photo = photoscript_photo(photo)
|
||||||
|
ps_photo.location = (latitude, longitude)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user