Files

80 lines
2.2 KiB
Python

from __future__ import annotations
import json
import os
import subprocess
import tempfile
from pathlib import Path
from typing import Any
from tools.executables import require_executable
def require_exiftool() -> str:
return require_executable("exiftool")
def _use_windows_argument_file() -> bool:
return os.name == "nt"
def run_exiftool_command(
executable: str,
args: list[str],
**run_kwargs: Any,
) -> subprocess.CompletedProcess:
"""Run ExifTool with Unicode-safe filename arguments on Windows."""
command = [executable, "-charset", "filename=UTF8", *args]
if not _use_windows_argument_file():
return subprocess.run(command, **run_kwargs)
# ExifTool can't reliably receive arbitrary Unicode paths on the Windows
# command line. The outer path is ASCII and the UTF-8 argument file holds
# the actual paths and options.
with tempfile.TemporaryDirectory(prefix="mbt-exiftool-") as temp_dir:
argument_file = Path(temp_dir) / "arguments.txt"
argument_file.write_text("\n".join(args) + "\n", encoding="utf-8")
return subprocess.run(
[executable, "-charset", "filename=UTF8", "-@", argument_file.name],
cwd=temp_dir,
**run_kwargs,
)
def run_exiftool_json(
executable: str,
paths: list[Path],
*,
quicktime_utc: bool = True,
) -> list[dict]:
results: list[dict] = []
for start in range(0, len(paths), 80):
chunk = paths[start : start + 80]
args = [
"-j",
"-G",
]
if quicktime_utc:
args.extend(["-api", "QuickTimeUTC=1"])
args.extend(str(path) for path in chunk)
completed = run_exiftool_command(
executable,
args,
check=True,
capture_output=True,
text=True,
)
results.extend(json.loads(completed.stdout or "[]"))
return results
def run_exiftool_write(executable: str, path: Path, args: list[str]) -> None:
if not args:
return
command = [
"-overwrite_original",
*args,
str(path),
]
run_exiftool_command(executable, command, check=True)