From 3999e54f6c699539b2ba42a6cdbe37ae84d783ad Mon Sep 17 00:00:00 2001 From: Rhet Turnbull Date: Tue, 25 Jul 2023 06:44:39 -0700 Subject: [PATCH] Feature custom sidecar 1123 cache (#1131) * Added caching to Template, fixed typos * Added additional sidecar tests --- examples/custom_sidecar_json.mako | 11 +++- osxphotos/cli/export.py | 4 +- osxphotos/cli/sidecar.py | 9 ++- tests/test_cli_export_sidecar_template.py | 75 +++++++++++++++++++++++ 4 files changed, 93 insertions(+), 6 deletions(-) diff --git a/examples/custom_sidecar_json.mako b/examples/custom_sidecar_json.mako index 93baa937..3df45458 100644 --- a/examples/custom_sidecar_json.mako +++ b/examples/custom_sidecar_json.mako @@ -1,6 +1,11 @@ <%doc> -Mako template to dump a full json representation of the photo object -Can be run from the command line with: -osxphotos export /path/to/export --sidecar-template custom_sidecar_json.mako "{filepath}.json" yes no yes + Mako template to dump a full json representation of the photo object + Can be run from the command line with: + osxphotos export /path/to/export --sidecar-template custom_sidecar_json.mako "{filepath}.json" yes no yes + + The template will be passed three variables for rendering: + photo: a PhotoInfo object for the photo being exported + photo_path: a pathlib.Path object for the photo file being exported + sidecar_path: a pathlib.Path object for the sidecar file being written ${photo.json(shallow=False, indent=4)} \ No newline at end of file diff --git a/osxphotos/cli/export.py b/osxphotos/cli/export.py index 65dced26..7aab7dd0 100644 --- a/osxphotos/cli/export.py +++ b/osxphotos/cli/export.py @@ -358,9 +358,9 @@ from .verbose import get_verbose_console, verbose_print "The template will passed the following variables: photo (PhotoInfo object for the photo being exported), " "sidecar_path (pathlib.Path object for the path to the sidecar being written), and " "photo_path (pathlib.Path object for the path to the exported photo. " - "SIDECAR_TEMPLATE_FILENAME must be a valid template string (see Templating System in help) " + "SIDECAR_FILENAME_TEMPLATE must be a valid template string (see Templating System in help) " "which will be rendered to generate the filename of the sidecar file. " - "The `{filepath}` template variable may be used in the SIDECAR_TEMPLATE_FILENAME to refer to the filename of the " + "The `{filepath}` template variable may be used in the SIDECAR_FILENAME_TEMPLATE to refer to the filename of the " "photo being exported. " "WRITE_SKIPPED is a boolean value (true/false, yes/no, 1/0 are all valid values) and indicates whether or not " "write the sidecar file even if the photo is skipped during export. " diff --git a/osxphotos/cli/sidecar.py b/osxphotos/cli/sidecar.py index 02302982..854aad2a 100644 --- a/osxphotos/cli/sidecar.py +++ b/osxphotos/cli/sidecar.py @@ -3,6 +3,7 @@ from __future__ import annotations import pathlib +from functools import cache from typing import Callable import click @@ -13,6 +14,12 @@ from osxphotos.photoinfo import PhotoInfo from osxphotos.phototemplate import PhotoTemplate, RenderOptions +@cache +def get_template(template: str) -> Template: + """Get template from cache or load from file""" + return Template(filename=template) + + def generate_user_sidecar( photo: PhotoInfo, export_results: ExportResults, @@ -123,7 +130,7 @@ def _render_sidecar_and_write_data( dry_run: bool, ): """Render sidecar template and write data to file""" - sidecar = Template(filename=template_file) + sidecar = get_template(template_file) sidecar_data = sidecar.render( photo=photo, sidecar_path=pathlib.Path(template_filename), diff --git a/tests/test_cli_export_sidecar_template.py b/tests/test_cli_export_sidecar_template.py index f49a5b70..8a66faa2 100644 --- a/tests/test_cli_export_sidecar_template.py +++ b/tests/test_cli_export_sidecar_template.py @@ -15,6 +15,7 @@ PHOTOS_DB = "./tests/Test-10.15.7.photoslibrary" PHOTO_UUID = "E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51" # wedding.jpg SIDECAR_FILENAME = "wedding.jpg.txt" +SIDECAR_FILENAME_2 = "wedding.jpg.sidecar" SIDECAR_DATA = """ @@ -23,6 +24,14 @@ Sidecar: wedding.jpg.txt UUID: E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51 Rating: ★★★★★ """ +SIDECAR_DATA_2 = """ + + +Sidecar: wedding.jpg.sidecar + Photo: wedding.jpg + UUID: E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51 + Rating: ★★★★★ +""" def test_export_sidecar_template_1(): @@ -401,3 +410,69 @@ def test_export_sidecar_template_report_db(): else: assert row[1] == 0 assert found_sidecar + + +def test_export_sidecar_template_multiple(): + """test export with multiple --sidecar-template options""" + runner = CliRunner() + cwd = os.getcwd() + # pylint: disable=not-context-manager + with runner.isolated_filesystem(): + result = runner.invoke( + export, + [ + "--library", + os.path.join(cwd, PHOTOS_DB), + ".", + "-V", + "--uuid", + PHOTO_UUID, + "--sidecar-template", + os.path.join(cwd, "tests", "custom_sidecar.mako"), + "{filepath}.txt", + "no", + "no", + "no", + "--sidecar-template", + os.path.join(cwd, "tests", "custom_sidecar.mako"), + "{filepath}.sidecar", + "no", + "no", + "no", + ], + ) + assert result.exit_code == 0 + + sidecar_file = pathlib.Path(SIDECAR_FILENAME) + assert sidecar_file.exists() + sidecar_data = sidecar_file.read_text() + assert sidecar_data == SIDECAR_DATA + + sidecar_file = pathlib.Path(SIDECAR_FILENAME_2) + assert sidecar_file.exists() + sidecar_data = sidecar_file.read_text() + assert sidecar_data == SIDECAR_DATA_2 + + +def test_export_sidecar_template_full_library(): + """test export with --sidecar-template option against full library (repeated calls to generate sidecar files))""" + runner = CliRunner() + cwd = os.getcwd() + # pylint: disable=not-context-manager + with runner.isolated_filesystem(): + result = runner.invoke( + export, + [ + "--library", + os.path.join(cwd, PHOTOS_DB), + ".", + "-V", + "--sidecar-template", + os.path.join(cwd, "tests", "custom_sidecar.mako"), + "{filepath}.txt", + "no", + "no", + "no", + ], + ) + assert result.exit_code == 0