Added --exiftool-option to CLI, closes #298

This commit is contained in:
Rhet Turnbull
2020-12-21 07:32:38 -08:00
parent aca19f4063
commit a4bbb6492d
8 changed files with 137 additions and 13 deletions

View File

@@ -1366,6 +1366,17 @@ def query(
"(video files only): QuickTime:CreationDate; QuickTime:CreateDate; QuickTime:ModifyDate (see also --ignore-date-modified); "
"QuickTime:GPSCoordinates; UserData:GPSCoordinates.",
)
@click.option(
"--exiftool-option",
multiple=True,
metavar="OPTION",
help="Optional flag/option to pass to exiftool when using --exiftool. "
"For example, --exiftool-option '-m' to ignore minor warnings. "
"Specify these as you would on the exiftool command line. "
"See exiftool docs at https://exiftool.org/exiftool_pod.html for full list of options. "
"More than one option may be specified with by repeating the option, e.g. "
"--exiftool-option '-m' --exiftool-option '-F'. ",
)
@click.option(
"--ignore-date-modified",
is_flag=True,
@@ -1550,6 +1561,7 @@ def export(
download_missing,
dest,
exiftool,
exiftool_option,
ignore_date_modified,
portrait,
not_portrait,
@@ -1747,6 +1759,7 @@ def export(
("missing", ("download_missing", "use_photos_export")),
("jpeg_quality", ("convert_to_jpeg")),
("ignore_signature", ("update")),
("exiftool_option", ("exiftool")),
]
try:
cfg.validate(exclusive=exclusive_options, dependent=dependent_options, cli=True)
@@ -1998,6 +2011,7 @@ def export(
jpeg_quality=jpeg_quality,
ignore_date_modified=ignore_date_modified,
use_photokit=use_photokit,
exiftool_option=exiftool_option,
)
results += export_results
@@ -2045,6 +2059,7 @@ def export(
jpeg_quality=jpeg_quality,
ignore_date_modified=ignore_date_modified,
use_photokit=use_photokit,
exiftool_option=exiftool_option,
)
results += export_results
@@ -2589,6 +2604,7 @@ def export_photo(
jpeg_quality=1.0,
ignore_date_modified=False,
use_photokit=False,
exiftool_option=None,
):
"""Helper function for export that does the actual export
@@ -2622,6 +2638,7 @@ def export_photo(
convert_to_jpeg: boolean; if True, converts non-jpeg images to jpeg
jpeg_quality: float in range 0.0 <= jpeg_quality <= 1.0. A value of 1.0 specifies use best quality, a value of 0.0 specifies use maximum compression.
ignore_date_modified: if True, sets EXIF:ModifyDate to EXIF:DateTimeOriginal even if date_modified is set
exiftool_option: optional list flags (e.g. ["-m", "-F"]) to pass to exiftool
Returns:
list of path(s) of exported photo or None if photo was missing
@@ -2767,12 +2784,21 @@ def export_photo(
ignore_date_modified=ignore_date_modified,
use_photokit=use_photokit,
verbose=verbose_,
exiftool_flags=exiftool_option,
)
results += export_results
for warning_ in export_results.exiftool_warning:
verbose_(f"exiftool warning for file {warning_[0]}: {warning_[1]}")
verbose_(
f"exiftool warning for file {warning_[0]}: {warning_[1]}"
)
for error_ in export_results.exiftool_error:
click.echo(click.style(f"exiftool error for file {error_[0]}: {error_[1]}", fg=CLI_COLOR_ERROR),err=True)
click.echo(
click.style(
f"exiftool error for file {error_[0]}: {error_[1]}",
fg=CLI_COLOR_ERROR,
),
err=True,
)
except Exception as e:
click.echo(
@@ -2862,12 +2888,21 @@ def export_photo(
ignore_date_modified=ignore_date_modified,
use_photokit=use_photokit,
verbose=verbose_,
exiftool_flags=exiftool_option,
)
results += export_results_edited
for warning_ in export_results_edited.exiftool_warning:
verbose_(f"exiftool warning for file {warning_[0]}: {warning_[1]}")
verbose_(
f"exiftool warning for file {warning_[0]}: {warning_[1]}"
)
for error_ in export_results_edited.exiftool_error:
click.echo(click.style(f"exiftool error for file {error_[0]}: {error_[1]}", fg=CLI_COLOR_ERROR),err=True)
click.echo(
click.style(
f"exiftool error for file {error_[0]}: {error_[1]}",
fg=CLI_COLOR_ERROR,
),
err=True,
)
except Exception as e:
click.echo(
click.style(

View File

@@ -1,5 +1,5 @@
""" version info """
__version__ = "0.38.8"
__version__ = "0.38.9"

View File

@@ -132,18 +132,21 @@ class _ExifToolProc:
class ExifTool:
""" Basic exiftool interface for reading and writing EXIF tags """
def __init__(self, filepath, exiftool=None, overwrite=True):
def __init__(self, filepath, exiftool=None, overwrite=True, flags=None):
""" Create ExifTool object
Args:
file: path to image file
exiftool: path to exiftool, if not specified will look in path
overwrite: if True, will overwrite image file without creating backup, default=False
file: path to image file
exiftool: path to exiftool, if not specified will look in path
overwrite: if True, will overwrite image file without creating backup, default=False
flags: optional list of exiftool flags to prepend to exiftool command when writing metadata (e.g. -m or -F)
Returns:
ExifTool instance
"""
self.file = filepath
self.overwrite = overwrite
self.flags = flags or []
self.data = {}
self.warning = None
self.error = None
@@ -249,14 +252,21 @@ class ExifTool:
commands.append("-overwrite_original")
filename = os.fsencode(self.file) if not no_file else b""
command_str = (
if self.flags:
command_str = b"\n".join([f.encode("utf-8") for f in self.flags])
command_str += b"\n"
else:
command_str = b""
command_str += (
b"\n".join([c.encode("utf-8") for c in commands])
+ b"\n"
+ filename
+ b"\n"
+ b"-execute\n"
)
# send the command
self._process.stdin.write(command_str)
self._process.stdin.flush()

View File

@@ -425,6 +425,7 @@ def export2(
ignore_date_modified=False,
use_photokit=False,
verbose=None,
exiftool_flags=None,
):
"""export photo, like export but with update and dry_run options
dest: must be valid destination path or exception raised
@@ -469,6 +470,7 @@ def export2(
jpeg_quality: float in range 0.0 <= jpeg_quality <= 1.0. A value of 1.0 specifies use best quality, a value of 0.0 specifies use maximum compression.
ignore_date_modified: for use with sidecar and exiftool; if True, sets EXIF:ModifyDate to EXIF:DateTimeOriginal even if date_modified is set
verbose: optional callable function to use for printing verbose text during processing; if None (default), does not print output.
exiftool_flags: optional list of flags to pass to exiftool when using exiftool option, e.g ["-m", "-F"]
Returns: ExportResults class
ExportResults has attributes:
@@ -972,6 +974,7 @@ def export2(
keyword_template=keyword_template,
description_template=description_template,
ignore_date_modified=ignore_date_modified,
flags=exiftool_flags,
)
if warning_:
exiftool_warning.append((exported_file, warning_))
@@ -1006,6 +1009,7 @@ def export2(
keyword_template=keyword_template,
description_template=description_template,
ignore_date_modified=ignore_date_modified,
flags=exiftool_flags,
)
if warning_:
exiftool_warning.append((exported_file, warning_))
@@ -1244,6 +1248,7 @@ def _write_exif_data(
keyword_template=None,
description_template=None,
ignore_date_modified=False,
flags=None,
):
"""write exif data to image file at filepath
@@ -1253,6 +1258,7 @@ def _write_exif_data(
use_persons_as_keywords: treat person names as keywords
keyword_template: (list of strings); list of template strings to render as keywords
ignore_date_modified: if True, sets EXIF:ModifyDate to EXIF:DateTimeOriginal even if date_modified is set
flags: optional list of exiftool flags to prepend to exiftool command when writing metadata (e.g. -m or -F)
Returns:
(warning, error) of warning and error strings if exiftool produces warnings or errors
@@ -1267,7 +1273,7 @@ def _write_exif_data(
ignore_date_modified=ignore_date_modified,
)
with ExifTool(filepath) as exiftool:
with ExifTool(filepath, flags=flags) as exiftool:
for exiftag, val in exif_info.items():
if type(val) == list:
for v in val: