* Initial implementation of exiftool command, #691 * updated comment [skip ci]
This commit is contained in:
@@ -80,19 +80,19 @@ def generate_sidecars(dbname, uuid_dict):
|
||||
|
||||
# generate JSON files
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}.json")
|
||||
json_ = exporter._exiftool_json_sidecar()
|
||||
json_ = exporter.exiftool_json_sidecar()
|
||||
with open(sidecar, "w") as file:
|
||||
file.write(json_)
|
||||
|
||||
# no tag groups
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_no_tag_groups.json")
|
||||
json_ = exporter._exiftool_json_sidecar(tag_groups=False)
|
||||
json_ = exporter.exiftool_json_sidecar(tag_groups=False)
|
||||
with open(sidecar, "w") as file:
|
||||
file.write(json_)
|
||||
|
||||
# ignore_date_modified
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_ignore_date_modified.json")
|
||||
json_ = exporter._exiftool_json_sidecar(
|
||||
json_ = exporter.exiftool_json_sidecar(
|
||||
ExportOptions(ignore_date_modified=True)
|
||||
)
|
||||
with open(sidecar, "w") as file:
|
||||
@@ -100,7 +100,7 @@ def generate_sidecars(dbname, uuid_dict):
|
||||
|
||||
# keyword_template
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_keyword_template.json")
|
||||
json_ = exporter._exiftool_json_sidecar(
|
||||
json_ = exporter.exiftool_json_sidecar(
|
||||
ExportOptions(keyword_template=["{folder_album}"])
|
||||
)
|
||||
with open(sidecar, "w") as file:
|
||||
@@ -108,7 +108,7 @@ def generate_sidecars(dbname, uuid_dict):
|
||||
|
||||
# persons_as_keywords
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_persons_as_keywords.json")
|
||||
json_ = exporter._exiftool_json_sidecar(
|
||||
json_ = exporter.exiftool_json_sidecar(
|
||||
ExportOptions(use_persons_as_keywords=True)
|
||||
)
|
||||
with open(sidecar, "w") as file:
|
||||
@@ -116,7 +116,7 @@ def generate_sidecars(dbname, uuid_dict):
|
||||
|
||||
# albums_as_keywords
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_albums_as_keywords.json")
|
||||
json_ = exporter._exiftool_json_sidecar(
|
||||
json_ = exporter.exiftool_json_sidecar(
|
||||
ExportOptions(use_albums_as_keywords=True)
|
||||
)
|
||||
with open(sidecar, "w") as file:
|
||||
|
||||
258
tests/test_cli_exiftool.py
Normal file
258
tests/test_cli_exiftool.py
Normal file
@@ -0,0 +1,258 @@
|
||||
"""Tests for `osxphotos exiftool` command."""
|
||||
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
from osxphotos.cli.exiftool_cli import exiftool
|
||||
from osxphotos.cli.export import export
|
||||
from osxphotos.exiftool import ExifTool, get_exiftool_path
|
||||
|
||||
from .test_cli import CLI_EXIFTOOL, PHOTOS_DB_15_7
|
||||
|
||||
# determine if exiftool installed so exiftool tests can be skipped
|
||||
try:
|
||||
exiftool_path = get_exiftool_path()
|
||||
except FileNotFoundError:
|
||||
exiftool_path = None
|
||||
|
||||
|
||||
@pytest.mark.skipif(exiftool_path is None, reason="exiftool not installed")
|
||||
def test_export_exiftool():
|
||||
"""Test osxphotos exiftool"""
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
|
||||
with runner.isolated_filesystem() as temp_dir:
|
||||
uuid_option = []
|
||||
for uuid in CLI_EXIFTOOL:
|
||||
uuid_option.extend(("--uuid", uuid))
|
||||
|
||||
# first, export without --exiftool
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
".",
|
||||
"-V",
|
||||
*uuid_option,
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
files = glob.glob("*")
|
||||
assert sorted(files) == sorted(
|
||||
[CLI_EXIFTOOL[uuid]["File:FileName"] for uuid in CLI_EXIFTOOL]
|
||||
)
|
||||
|
||||
# now, run exiftool command to update exiftool metadata
|
||||
result = runner.invoke(
|
||||
exiftool,
|
||||
["--db", os.path.join(cwd, PHOTOS_DB_15_7), "-V", "--db-config", temp_dir],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
exif = ExifTool(CLI_EXIFTOOL[uuid]["File:FileName"]).asdict()
|
||||
for key in CLI_EXIFTOOL[uuid]:
|
||||
if type(exif[key]) == list:
|
||||
assert sorted(exif[key]) == sorted(CLI_EXIFTOOL[uuid][key])
|
||||
else:
|
||||
assert exif[key] == CLI_EXIFTOOL[uuid][key]
|
||||
|
||||
# now, export with --exiftool --update, no files should be updated
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
".",
|
||||
"-V",
|
||||
"--exiftool",
|
||||
"--update",
|
||||
*uuid_option,
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert f"exported: 0, updated: 0, skipped: {len(CLI_EXIFTOOL)}" in result.output
|
||||
|
||||
|
||||
@pytest.mark.skipif(exiftool_path is None, reason="exiftool not installed")
|
||||
def test_export_exiftool_album_keyword():
|
||||
"""Test osxphotos exiftool with --album-template."""
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
|
||||
with runner.isolated_filesystem() as temp_dir:
|
||||
# first, export without --exiftool
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
".",
|
||||
"-V",
|
||||
"--album",
|
||||
"Pumpkin Farm",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
files = glob.glob("*")
|
||||
assert len(files) == 3
|
||||
|
||||
# now, run exiftool command to update exiftool metadata
|
||||
result = runner.invoke(
|
||||
exiftool,
|
||||
[
|
||||
"--db",
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
"-V",
|
||||
"--db-config",
|
||||
"--report",
|
||||
"exiftool.json",
|
||||
"--album-keyword",
|
||||
temp_dir,
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
report = json.load(open("exiftool.json", "r"))
|
||||
assert len(report) == 3
|
||||
|
||||
# verify exiftool metadata was updated
|
||||
for file in report:
|
||||
exif = ExifTool(file["filename"]).asdict()
|
||||
assert "Pumpkin Farm" in exif["IPTC:Keywords"]
|
||||
|
||||
# now, export with --exiftool --update, no files should be updated
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
".",
|
||||
"-V",
|
||||
"--exiftool",
|
||||
"--update",
|
||||
"--album",
|
||||
"Pumpkin Farm",
|
||||
"--album-keyword",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert f"exported: 0, updated: 0, skipped: 3" in result.output
|
||||
|
||||
|
||||
@pytest.mark.skipif(exiftool_path is None, reason="exiftool not installed")
|
||||
def test_export_exiftool_keyword_template():
|
||||
"""Test osxphotos exiftool with --keyword-template."""
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
|
||||
with runner.isolated_filesystem() as temp_dir:
|
||||
uuid_option = []
|
||||
for uuid in CLI_EXIFTOOL:
|
||||
uuid_option.extend(("--uuid", uuid))
|
||||
|
||||
# first, export without --exiftool
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
".",
|
||||
"-V",
|
||||
*uuid_option,
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
# now, run exiftool command to update exiftool metadata
|
||||
result = runner.invoke(
|
||||
exiftool,
|
||||
[
|
||||
"--db",
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
"-V",
|
||||
"--db-config",
|
||||
"--keyword-template",
|
||||
"FOO",
|
||||
temp_dir,
|
||||
"--report",
|
||||
"exiftool.json",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
report = json.load(open("exiftool.json", "r"))
|
||||
for file in report:
|
||||
exif = ExifTool(file["filename"]).asdict()
|
||||
assert "FOO" in exif["IPTC:Keywords"]
|
||||
|
||||
# now, export with --exiftool --update, no files should be updated
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
".",
|
||||
"-V",
|
||||
"--exiftool",
|
||||
"--keyword-template",
|
||||
"FOO",
|
||||
"--update",
|
||||
*uuid_option,
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert f"exported: 0, updated: 0, skipped: {len(CLI_EXIFTOOL)}" in result.output
|
||||
|
||||
|
||||
@pytest.mark.skipif(exiftool_path is None, reason="exiftool not installed")
|
||||
def test_export_exiftool_load_config():
|
||||
"""Test osxphotos exiftool with --load-config"""
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
|
||||
with runner.isolated_filesystem() as temp_dir:
|
||||
uuid_option = []
|
||||
for uuid in CLI_EXIFTOOL:
|
||||
uuid_option.extend(("--uuid", uuid))
|
||||
|
||||
# first, export without --exiftool
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
".",
|
||||
"-V",
|
||||
"--save-config",
|
||||
"config.toml",
|
||||
*uuid_option,
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
# now, run exiftool command to update exiftool metadata
|
||||
result = runner.invoke(
|
||||
exiftool,
|
||||
["-V", "--load-config", "config.toml", temp_dir],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
exif = ExifTool(CLI_EXIFTOOL[uuid]["File:FileName"]).asdict()
|
||||
for key in CLI_EXIFTOOL[uuid]:
|
||||
if type(exif[key]) == list:
|
||||
assert sorted(exif[key]) == sorted(CLI_EXIFTOOL[uuid][key])
|
||||
else:
|
||||
assert exif[key] == CLI_EXIFTOOL[uuid][key]
|
||||
|
||||
# now, export with --exiftool --update, no files should be updated
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
".",
|
||||
"-V",
|
||||
"--exiftool",
|
||||
"--update",
|
||||
*uuid_option,
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert f"exported: 0, updated: 0, skipped: {len(CLI_EXIFTOOL)}" in result.output
|
||||
@@ -1,6 +1,8 @@
|
||||
""" test ConfigOptions class """
|
||||
|
||||
import pathlib
|
||||
from io import StringIO
|
||||
|
||||
import pytest
|
||||
import toml
|
||||
|
||||
@@ -43,6 +45,15 @@ def test_write_to_file_load_from_file(tmpdir):
|
||||
assert cfg2.bar
|
||||
|
||||
|
||||
def test_load_from_str(tmpdir):
|
||||
cfg = ConfigOptions("test", VARS)
|
||||
cfg.bar = True
|
||||
cfg_str = cfg.write_to_str()
|
||||
cfg2 = ConfigOptions("test", VARS).load_from_str(cfg_str)
|
||||
assert cfg2.foo == "bar"
|
||||
assert cfg2.bar
|
||||
|
||||
|
||||
def test_load_from_file_error(tmpdir):
|
||||
cfg_file = pathlib.Path(str(tmpdir)) / "test.toml"
|
||||
cfg = ConfigOptions("test", VARS)
|
||||
|
||||
@@ -404,7 +404,7 @@ def test_exiftool_json_sidecar(photosdb):
|
||||
with open(str(pathlib.Path(SIDECAR_DIR) / f"{uuid}.json"), "r") as fp:
|
||||
json_expected = json.load(fp)[0]
|
||||
|
||||
json_got = PhotoExporter(photo)._exiftool_json_sidecar()
|
||||
json_got = PhotoExporter(photo).exiftool_json_sidecar()
|
||||
json_got = json.loads(json_got)[0]
|
||||
|
||||
assert json_got == json_expected
|
||||
@@ -420,7 +420,7 @@ def test_exiftool_json_sidecar_ignore_date_modified(photosdb):
|
||||
) as fp:
|
||||
json_expected = json.load(fp)[0]
|
||||
|
||||
json_got = PhotoExporter(photo)._exiftool_json_sidecar(
|
||||
json_got = PhotoExporter(photo).exiftool_json_sidecar(
|
||||
ExportOptions(ignore_date_modified=True)
|
||||
)
|
||||
json_got = json.loads(json_got)[0]
|
||||
@@ -453,7 +453,7 @@ def test_exiftool_json_sidecar_keyword_template_long(capsys, photosdb):
|
||||
|
||||
long_str = "x" * (_MAX_IPTC_KEYWORD_LEN + 1)
|
||||
photos[0]._verbose = print
|
||||
json_got = PhotoExporter(photos[0])._exiftool_json_sidecar(
|
||||
json_got = PhotoExporter(photos[0]).exiftool_json_sidecar(
|
||||
ExportOptions(keyword_template=[long_str])
|
||||
)
|
||||
json_got = json.loads(json_got)[0]
|
||||
@@ -479,7 +479,7 @@ def test_exiftool_json_sidecar_keyword_template(photosdb):
|
||||
str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_keyword_template.json"), "r"
|
||||
) as fp:
|
||||
json_expected = json.load(fp)
|
||||
json_got = PhotoExporter(photo)._exiftool_json_sidecar(
|
||||
json_got = PhotoExporter(photo).exiftool_json_sidecar(
|
||||
ExportOptions(keyword_template=["{folder_album}"])
|
||||
)
|
||||
json_got = json.loads(json_got)
|
||||
@@ -497,7 +497,7 @@ def test_exiftool_json_sidecar_use_persons_keyword(photosdb):
|
||||
) as fp:
|
||||
json_expected = json.load(fp)[0]
|
||||
|
||||
json_got = PhotoExporter(photo)._exiftool_json_sidecar(
|
||||
json_got = PhotoExporter(photo).exiftool_json_sidecar(
|
||||
ExportOptions(use_persons_as_keywords=True)
|
||||
)
|
||||
json_got = json.loads(json_got)[0]
|
||||
@@ -515,7 +515,7 @@ def test_exiftool_json_sidecar_use_albums_keywords(photosdb):
|
||||
) as fp:
|
||||
json_expected = json.load(fp)
|
||||
|
||||
json_got = PhotoExporter(photo)._exiftool_json_sidecar(
|
||||
json_got = PhotoExporter(photo).exiftool_json_sidecar(
|
||||
ExportOptions(use_albums_as_keywords=True)
|
||||
)
|
||||
json_got = json.loads(json_got)
|
||||
@@ -530,7 +530,7 @@ def test_exiftool_sidecar(photosdb):
|
||||
with open(pathlib.Path(SIDECAR_DIR) / f"{uuid}_no_tag_groups.json", "r") as fp:
|
||||
json_expected = fp.read()
|
||||
|
||||
json_got = PhotoExporter(photo)._exiftool_json_sidecar(tag_groups=False)
|
||||
json_got = PhotoExporter(photo).exiftool_json_sidecar(tag_groups=False)
|
||||
|
||||
assert json_got == json_expected
|
||||
|
||||
|
||||
@@ -337,7 +337,7 @@ def test_exiftool_json_sidecar(photosdb):
|
||||
with open(str(pathlib.Path(SIDECAR_DIR) / f"{uuid}.json"), "r") as fp:
|
||||
json_expected = json.load(fp)[0]
|
||||
|
||||
json_got = PhotoExporter(photo)._exiftool_json_sidecar()
|
||||
json_got = PhotoExporter(photo).exiftool_json_sidecar()
|
||||
json_got = json.loads(json_got)[0]
|
||||
|
||||
assert json_got == json_expected
|
||||
|
||||
Reference in New Issue
Block a user