Added --description-template to CLI, closes #166
This commit is contained in:
@@ -1146,6 +1146,18 @@ def query(
|
||||
'--keyword-template "{created.year}" '
|
||||
"See Templating System below.",
|
||||
)
|
||||
@click.option(
|
||||
"--description-template",
|
||||
metavar="TEMPLATE",
|
||||
multiple=False,
|
||||
default=None,
|
||||
help="For use with --exiftool, --sidecar; specify a template string to use as "
|
||||
"description in the form '{name,DEFAULT}' "
|
||||
"This is the same format as --directory. For example, if you wanted to append "
|
||||
"'exported with osxphotos on [today's date]' to the description, you could specify "
|
||||
'--description-template "{descr} exported with osxphotos on {today.date}" '
|
||||
"See Templating System below.",
|
||||
)
|
||||
@click.option(
|
||||
"--current-name",
|
||||
is_flag=True,
|
||||
@@ -1260,6 +1272,7 @@ def export(
|
||||
person_keyword,
|
||||
album_keyword,
|
||||
keyword_template,
|
||||
description_template,
|
||||
current_name,
|
||||
sidecar,
|
||||
only_photos,
|
||||
@@ -1505,6 +1518,7 @@ def export(
|
||||
album_keyword=album_keyword,
|
||||
person_keyword=person_keyword,
|
||||
keyword_template=keyword_template,
|
||||
description_template=description_template,
|
||||
export_db=export_db,
|
||||
fileutil=fileutil,
|
||||
dry_run=dry_run,
|
||||
@@ -1541,6 +1555,7 @@ def export(
|
||||
album_keyword=album_keyword,
|
||||
person_keyword=person_keyword,
|
||||
keyword_template=keyword_template,
|
||||
description_template=description_template,
|
||||
export_db=export_db,
|
||||
fileutil=fileutil,
|
||||
dry_run=dry_run,
|
||||
@@ -2012,6 +2027,7 @@ def export_photo(
|
||||
album_keyword=None,
|
||||
person_keyword=None,
|
||||
keyword_template=None,
|
||||
description_template=None,
|
||||
export_db=None,
|
||||
fileutil=FileUtil,
|
||||
dry_run=None,
|
||||
@@ -2039,6 +2055,7 @@ def export_photo(
|
||||
album_keyword: boolean; if True, exports album names as keywords in metadata
|
||||
person_keyword: boolean; if True, exports person names as keywords in metadata
|
||||
keyword_template: list of strings; if provided use rendered template strings as keywords
|
||||
description_template: string; optional template string that will be rendered for use as photo description
|
||||
export_db: export database instance compatible with ExportDB_ABC
|
||||
fileutil: file util class compatible with FileUtilABC
|
||||
dry_run: boolean; if True, doesn't actually export or update any files
|
||||
@@ -2113,6 +2130,7 @@ def export_photo(
|
||||
use_albums_as_keywords=album_keyword,
|
||||
use_persons_as_keywords=person_keyword,
|
||||
keyword_template=keyword_template,
|
||||
description_template=description_template,
|
||||
update=update,
|
||||
export_db=export_db,
|
||||
fileutil=fileutil,
|
||||
@@ -2168,6 +2186,7 @@ def export_photo(
|
||||
use_albums_as_keywords=album_keyword,
|
||||
use_persons_as_keywords=person_keyword,
|
||||
keyword_template=keyword_template,
|
||||
description_template=description_template,
|
||||
update=update,
|
||||
export_db=export_db,
|
||||
fileutil=fileutil,
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.30.2"
|
||||
__version__ = "0.30.3"
|
||||
|
||||
@@ -215,6 +215,7 @@ def export(
|
||||
use_albums_as_keywords=False,
|
||||
use_persons_as_keywords=False,
|
||||
keyword_template=None,
|
||||
description_template=None,
|
||||
):
|
||||
""" export photo
|
||||
dest: must be valid destination path (or exception raised)
|
||||
@@ -250,6 +251,7 @@ def export(
|
||||
use_persons_as_keywords: (boolean, default = False); if True, will include person names in keywords
|
||||
when exporting metadata with exiftool or sidecar
|
||||
keyword_template: (list of strings); list of template strings that will be rendered as used as keywords
|
||||
description_template: string; optional template string that will be rendered for use as photo description
|
||||
returns: list of photos exported
|
||||
"""
|
||||
|
||||
@@ -273,6 +275,7 @@ def export(
|
||||
use_albums_as_keywords=use_albums_as_keywords,
|
||||
use_persons_as_keywords=use_persons_as_keywords,
|
||||
keyword_template=keyword_template,
|
||||
description_template=description_template,
|
||||
)
|
||||
|
||||
return results.exported
|
||||
@@ -297,6 +300,7 @@ def export2(
|
||||
use_albums_as_keywords=False,
|
||||
use_persons_as_keywords=False,
|
||||
keyword_template=None,
|
||||
description_template=None,
|
||||
update=False,
|
||||
export_db=None,
|
||||
fileutil=FileUtil,
|
||||
@@ -336,6 +340,7 @@ def export2(
|
||||
use_persons_as_keywords: (boolean, default = False); if True, will include person names in keywords
|
||||
when exporting metadata with exiftool or sidecar
|
||||
keyword_template: (list of strings); list of template strings that will be rendered as used as keywords
|
||||
description_template: string; optional template string that will be rendered for use as photo description
|
||||
update: (boolean, default=False); if True export will run in update mode, that is, it will
|
||||
not export the photo if the current version already exists in the destination
|
||||
export_db: (ExportDB_ABC); instance of a class that conforms to ExportDB_ABC with methods
|
||||
@@ -670,6 +675,7 @@ def export2(
|
||||
use_albums_as_keywords=use_albums_as_keywords,
|
||||
use_persons_as_keywords=use_persons_as_keywords,
|
||||
keyword_template=keyword_template,
|
||||
description_template=description_template,
|
||||
)
|
||||
if not dry_run:
|
||||
try:
|
||||
@@ -685,6 +691,7 @@ def export2(
|
||||
use_albums_as_keywords=use_albums_as_keywords,
|
||||
use_persons_as_keywords=use_persons_as_keywords,
|
||||
keyword_template=keyword_template,
|
||||
description_template=description_template,
|
||||
)
|
||||
if not dry_run:
|
||||
try:
|
||||
@@ -712,6 +719,7 @@ def export2(
|
||||
use_albums_as_keywords=use_albums_as_keywords,
|
||||
use_persons_as_keywords=use_persons_as_keywords,
|
||||
keyword_template=keyword_template,
|
||||
description_template=description_template,
|
||||
)
|
||||
)[0]
|
||||
if old_data != current_data:
|
||||
@@ -727,6 +735,7 @@ def export2(
|
||||
use_albums_as_keywords=use_albums_as_keywords,
|
||||
use_persons_as_keywords=use_persons_as_keywords,
|
||||
keyword_template=keyword_template,
|
||||
description_template=description_template,
|
||||
)
|
||||
export_db.set_exifdata_for_file(
|
||||
exported_file,
|
||||
@@ -734,6 +743,7 @@ def export2(
|
||||
use_albums_as_keywords=use_albums_as_keywords,
|
||||
use_persons_as_keywords=use_persons_as_keywords,
|
||||
keyword_template=keyword_template,
|
||||
description_template=description_template,
|
||||
),
|
||||
)
|
||||
export_db.set_stat_exif_for_file(
|
||||
@@ -749,6 +759,7 @@ def export2(
|
||||
use_albums_as_keywords=use_albums_as_keywords,
|
||||
use_persons_as_keywords=use_persons_as_keywords,
|
||||
keyword_template=keyword_template,
|
||||
description_template=description_template,
|
||||
)
|
||||
export_db.set_exifdata_for_file(
|
||||
exported_file,
|
||||
@@ -756,6 +767,7 @@ def export2(
|
||||
use_albums_as_keywords=use_albums_as_keywords,
|
||||
use_persons_as_keywords=use_persons_as_keywords,
|
||||
keyword_template=keyword_template,
|
||||
description_template=description_template,
|
||||
),
|
||||
)
|
||||
export_db.set_stat_exif_for_file(
|
||||
@@ -955,6 +967,7 @@ def _write_exif_data(
|
||||
use_albums_as_keywords=False,
|
||||
use_persons_as_keywords=False,
|
||||
keyword_template=None,
|
||||
description_template=None,
|
||||
):
|
||||
""" write exif data to image file at filepath
|
||||
filepath: full path to the image file """
|
||||
@@ -966,6 +979,7 @@ def _write_exif_data(
|
||||
use_albums_as_keywords=use_albums_as_keywords,
|
||||
use_persons_as_keywords=use_persons_as_keywords,
|
||||
keyword_template=keyword_template,
|
||||
description_template=description_template,
|
||||
)
|
||||
)[0]
|
||||
for exiftag, val in exif_info.items():
|
||||
@@ -984,6 +998,7 @@ def _exiftool_json_sidecar(
|
||||
use_albums_as_keywords=False,
|
||||
use_persons_as_keywords=False,
|
||||
keyword_template=None,
|
||||
description_template=None,
|
||||
):
|
||||
""" return json string of EXIF details in exiftool sidecar format
|
||||
Does not include all the EXIF fields as those are likely already in the image
|
||||
@@ -1009,7 +1024,13 @@ def _exiftool_json_sidecar(
|
||||
exif = {}
|
||||
exif["_CreatedBy"] = "osxphotos, https://github.com/RhetTbull/osxphotos"
|
||||
|
||||
if self.description:
|
||||
if description_template is not None:
|
||||
description = self.render_template(
|
||||
description_template, expand_inplace=True, inplace_sep=", "
|
||||
)[0]
|
||||
exif["EXIF:ImageDescription"] = description
|
||||
exif["XMP:Description"] = description
|
||||
elif self.description:
|
||||
exif["EXIF:ImageDescription"] = self.description
|
||||
exif["XMP:Description"] = self.description
|
||||
|
||||
@@ -1112,16 +1133,25 @@ def _xmp_sidecar(
|
||||
use_albums_as_keywords=False,
|
||||
use_persons_as_keywords=False,
|
||||
keyword_template=None,
|
||||
description_template=None,
|
||||
):
|
||||
""" returns string for XMP sidecar
|
||||
use_albums_as_keywords: treat album names as keywords
|
||||
use_persons_as_keywords: treat person names as keywords
|
||||
keyword_template: (list of strings); list of template strings to render as keywords """
|
||||
keyword_template: (list of strings); list of template strings to render as keywords
|
||||
description_template: string; optional template string that will be rendered for use as photo description """
|
||||
|
||||
# TODO: add additional fields to XMP file?
|
||||
|
||||
xmp_template = Template(filename=os.path.join(_TEMPLATE_DIR, _XMP_TEMPLATE_NAME))
|
||||
|
||||
if description_template is not None:
|
||||
description = self.render_template(
|
||||
description_template, expand_inplace=True, inplace_sep=", "
|
||||
)[0]
|
||||
else:
|
||||
description = self.description if self.description is not None else ""
|
||||
|
||||
keyword_list = []
|
||||
if self.keywords:
|
||||
keyword_list.extend(self.keywords)
|
||||
@@ -1178,7 +1208,11 @@ def _xmp_sidecar(
|
||||
subject_list = list(self.keywords) + person_list
|
||||
|
||||
xmp_str = xmp_template.render(
|
||||
photo=self, keywords=keyword_list, persons=person_list, subjects=subject_list
|
||||
photo=self,
|
||||
description=description,
|
||||
keywords=keyword_list,
|
||||
persons=person_list,
|
||||
subjects=subject_list,
|
||||
)
|
||||
|
||||
# remove extra lines that mako inserts from template
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
||||
${dc_description(photo.description)}
|
||||
${dc_description(description)}
|
||||
${dc_title(photo.title)}
|
||||
${dc_subject(subjects)}
|
||||
${dc_datecreated(photo.date)}
|
||||
|
||||
@@ -197,7 +197,13 @@ CLI_EXPORT_RAW_EDITED = [
|
||||
]
|
||||
CLI_EXPORT_RAW_EDITED_ORIGINAL = ["IMG_0476_2.CR2", "IMG_0476_2_edited.jpeg"]
|
||||
|
||||
CLI_UUID_DICT_15_5 = {"intrash": "71E3E212-00EB-430D-8A63-5E294B268554"}
|
||||
CLI_UUID_DICT_15_5 = {
|
||||
"intrash": "71E3E212-00EB-430D-8A63-5E294B268554",
|
||||
"template": "F12384F6-CD17-4151-ACBA-AE0E3688539E",
|
||||
}
|
||||
|
||||
CLI_TEMPLATE_SIDECAR_FILENAME = "Pumkins1.json"
|
||||
|
||||
CLI_UUID_DICT_14_6 = {"intrash": "3tljdX43R8+k6peNHVrJNQ"}
|
||||
|
||||
PHOTOS_NOT_IN_TRASH_LEN_14_6 = 7
|
||||
@@ -1095,6 +1101,48 @@ def test_export_sidecar():
|
||||
assert sorted(files) == sorted(CLI_EXPORT_SIDECAR_FILENAMES)
|
||||
|
||||
|
||||
def test_export_sidecar_templates():
|
||||
import json
|
||||
import os
|
||||
import os.path
|
||||
import osxphotos
|
||||
|
||||
from osxphotos.__main__ import cli
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
# pylint: disable=not-context-manager
|
||||
with runner.isolated_filesystem():
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[
|
||||
"export",
|
||||
"--db",
|
||||
os.path.join(cwd, PHOTOS_DB_15_5),
|
||||
".",
|
||||
"--sidecar=json",
|
||||
f"--uuid={CLI_UUID_DICT_15_5['template']}",
|
||||
"-V",
|
||||
"--keyword-template",
|
||||
"{person}",
|
||||
"--description-template",
|
||||
"{descr} {person} {keyword} {album}",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert os.path.isfile(CLI_TEMPLATE_SIDECAR_FILENAME)
|
||||
with open(CLI_TEMPLATE_SIDECAR_FILENAME, "r") as jsonfile:
|
||||
exifdata = json.load(jsonfile)
|
||||
assert (
|
||||
exifdata[0]["XMP:Description"][0]
|
||||
== "Girls with pumpkins Katie, Suzy Kids Pumpkin Farm, Test Album"
|
||||
)
|
||||
assert (
|
||||
exifdata[0]["EXIF:ImageDescription"][0]
|
||||
== "Girls with pumpkins Katie, Suzy Kids Pumpkin Farm, Test Album"
|
||||
)
|
||||
|
||||
|
||||
def test_export_live():
|
||||
import glob
|
||||
import os
|
||||
|
||||
Reference in New Issue
Block a user