80 lines
2.2 KiB
Python
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)
|