Removed debug code from exiftool, fixed #641
This commit is contained in:
@@ -1741,7 +1741,7 @@ Substitution Description
|
||||
{lf} A line feed: '\n', alias for {newline}
|
||||
{cr} A carriage return: '\r'
|
||||
{crlf} a carriage return + line feed: '\r\n'
|
||||
{osxphotos_version} The osxphotos version, e.g. '0.46.2'
|
||||
{osxphotos_version} The osxphotos version, e.g. '0.46.4'
|
||||
{osxphotos_cmd_line} The full command line used to run osxphotos
|
||||
|
||||
The following substitutions may result in multiple values. Thus if specified for
|
||||
@@ -3645,7 +3645,7 @@ The following template field substitutions are availabe for use the templating s
|
||||
|{lf}|A line feed: '\n', alias for {newline}|
|
||||
|{cr}|A carriage return: '\r'|
|
||||
|{crlf}|a carriage return + line feed: '\r\n'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.46.2'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.46.4'|
|
||||
|{osxphotos_cmd_line}|The full command line used to run osxphotos|
|
||||
|{album}|Album(s) photo is contained in|
|
||||
|{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder|
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Sphinx build info version 1
|
||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: 3bdc7daae06c46fa0e6357e497a27088
|
||||
config: 4fd4a10e261cc9bab3c5f7edf97d5f38
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Overview: module code — osxphotos 0.46.2 documentation</title>
|
||||
<title>Overview: module code — osxphotos 0.46.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>osxphotos.photoinfo — osxphotos 0.46.1 documentation</title>
|
||||
<title>osxphotos.photoinfo — osxphotos 0.46.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/alabaster.css" />
|
||||
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
|
||||
@@ -87,7 +87,7 @@
|
||||
<span class="kn">from</span> <span class="nn">.searchinfo</span> <span class="kn">import</span> <span class="n">SearchInfo</span>
|
||||
<span class="kn">from</span> <span class="nn">.text_detection</span> <span class="kn">import</span> <span class="n">detect_text</span>
|
||||
<span class="kn">from</span> <span class="nn">.uti</span> <span class="kn">import</span> <span class="n">get_preferred_uti_extension</span><span class="p">,</span> <span class="n">get_uti_for_extension</span>
|
||||
<span class="kn">from</span> <span class="nn">.utils</span> <span class="kn">import</span> <span class="n">_debug</span><span class="p">,</span> <span class="n">_get_resource_loc</span><span class="p">,</span> <span class="n">list_directory</span>
|
||||
<span class="kn">from</span> <span class="nn">.utils</span> <span class="kn">import</span> <span class="n">_debug</span><span class="p">,</span> <span class="n">_get_resource_loc</span><span class="p">,</span> <span class="n">list_directory</span><span class="p">,</span> <span class="n">_debug</span>
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"PhotoInfo"</span><span class="p">,</span> <span class="s2">"PhotoInfoNone"</span><span class="p">]</span>
|
||||
|
||||
@@ -621,7 +621,7 @@
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">ismissing</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""returns true if photo is missing from disk (which means it's not been downloaded from iCloud)</span>
|
||||
<span class="sd"> </span>
|
||||
|
||||
<span class="sd"> NOTE: the photos.db database uses an asynchrounous write-ahead log so changes in Photos</span>
|
||||
<span class="sd"> do not immediately get written to disk. In particular, I've noticed that downloading</span>
|
||||
<span class="sd"> an image from the cloud does not force the database to be updated until something else</span>
|
||||
|
||||
2
docs/_static/documentation_options.js
vendored
2
docs/_static/documentation_options.js
vendored
@@ -1,6 +1,6 @@
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||
VERSION: '0.46.2',
|
||||
VERSION: '0.46.4',
|
||||
LANGUAGE: 'None',
|
||||
COLLAPSE_INDEX: false,
|
||||
BUILDER: 'html',
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>osxphotos command line interface (CLI) — osxphotos 0.46.2 documentation</title>
|
||||
<title>osxphotos command line interface (CLI) — osxphotos 0.46.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Index — osxphotos 0.46.2 documentation</title>
|
||||
<title>Index — osxphotos 0.46.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Welcome to osxphotos’s documentation! — osxphotos 0.46.2 documentation</title>
|
||||
<title>Welcome to osxphotos’s documentation! — osxphotos 0.46.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>osxphotos — osxphotos 0.46.2 documentation</title>
|
||||
<title>osxphotos — osxphotos 0.46.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>osxphotos package — osxphotos 0.46.2 documentation</title>
|
||||
<title>osxphotos package — osxphotos 0.46.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Search — osxphotos 0.46.2 documentation</title>
|
||||
<title>Search — osxphotos 0.46.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.46.3"
|
||||
__version__ = "0.46.4"
|
||||
|
||||
@@ -105,10 +105,9 @@ class _ExifToolProc:
|
||||
|
||||
return cls.instance
|
||||
|
||||
def __init__(self, exiftool=None, debug=False):
|
||||
def __init__(self, exiftool=None):
|
||||
"""construct _ExifToolProc singleton object or return instance of already created object
|
||||
exiftool: optional path to exiftool binary (if not provided, will search path to find it)
|
||||
debug: optional bool to enable debugging output
|
||||
"""
|
||||
|
||||
if hasattr(self, "_process_running") and self._process_running:
|
||||
@@ -119,11 +118,8 @@ class _ExifToolProc:
|
||||
f"ignoring exiftool={exiftool}"
|
||||
)
|
||||
return
|
||||
self.debug = debug
|
||||
self._process_running = False
|
||||
self._exiftool = exiftool or get_exiftool_path()
|
||||
if self.debug:
|
||||
logging.debug(f"exiftool={self._exiftool}")
|
||||
self._start_proc()
|
||||
|
||||
@property
|
||||
@@ -177,17 +173,10 @@ class _ExifToolProc:
|
||||
self._process_running = True
|
||||
|
||||
EXIFTOOL_PROCESSES.append(self)
|
||||
if self.debug:
|
||||
logging.debug(
|
||||
"exiftool process started: {self._process} {self._process_running}"
|
||||
)
|
||||
|
||||
def _stop_proc(self):
|
||||
"""stop the exiftool process if it's running, otherwise, do nothing"""
|
||||
|
||||
if self.debug:
|
||||
logging.debug(f"exiftool process stopping: {self._process}")
|
||||
|
||||
if not self._process_running:
|
||||
return
|
||||
|
||||
@@ -207,16 +196,11 @@ class _ExifToolProc:
|
||||
del self._process
|
||||
self._process_running = False
|
||||
|
||||
if self.debug:
|
||||
logging.debug(f"exiftool process stopped: {self._process}")
|
||||
|
||||
|
||||
class ExifTool:
|
||||
"""Basic exiftool interface for reading and writing EXIF tags"""
|
||||
|
||||
def __init__(
|
||||
self, filepath, exiftool=None, overwrite=True, flags=None, debug=False
|
||||
):
|
||||
def __init__(self, filepath, exiftool=None, overwrite=True, flags=None):
|
||||
"""Create ExifTool object
|
||||
|
||||
Args:
|
||||
@@ -224,7 +208,6 @@ class ExifTool:
|
||||
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)
|
||||
debug: if True, enables debug output
|
||||
|
||||
Returns:
|
||||
ExifTool instance
|
||||
@@ -232,13 +215,12 @@ class ExifTool:
|
||||
self.file = filepath
|
||||
self.overwrite = overwrite
|
||||
self.flags = flags or []
|
||||
self.debug = debug
|
||||
self.data = {}
|
||||
self.warning = None
|
||||
self.error = None
|
||||
# if running as a context manager, self._context_mgr will be True
|
||||
self._context_mgr = False
|
||||
self._exiftoolproc = _ExifToolProc(exiftool=exiftool, debug=debug)
|
||||
self._exiftoolproc = _ExifToolProc(exiftool=exiftool)
|
||||
self._read_exif()
|
||||
|
||||
@property
|
||||
@@ -366,9 +348,6 @@ class ExifTool:
|
||||
+ b"-execute\n"
|
||||
)
|
||||
|
||||
if self.debug:
|
||||
logging.debug(f"running exiftool command: {command_str}")
|
||||
|
||||
# send the command
|
||||
self._process.stdin.write(command_str)
|
||||
self._process.stdin.flush()
|
||||
@@ -389,10 +368,6 @@ class ExifTool:
|
||||
error = "" if error == b"" else error.decode("utf-8")
|
||||
self.warning = warning
|
||||
self.error = error
|
||||
if self.debug:
|
||||
logging.debug(
|
||||
f"run_commands: output={output[:-EXIFTOOL_STAYOPEN_EOF_LEN]}, warning={warning}, error={error}"
|
||||
)
|
||||
|
||||
return output[:-EXIFTOOL_STAYOPEN_EOF_LEN], warning, error
|
||||
|
||||
@@ -417,8 +392,6 @@ class ExifTool:
|
||||
"""
|
||||
json_str, _, _ = self.run_commands("-json")
|
||||
if not json_str:
|
||||
if self.debug:
|
||||
logging.debug(f"empty json_str")
|
||||
return dict()
|
||||
json_str = unescape_str(json_str.decode("utf-8"))
|
||||
|
||||
@@ -427,8 +400,7 @@ class ExifTool:
|
||||
except Exception as e:
|
||||
# will fail with some commands, e.g --ext AVI which produces
|
||||
# 'No file with specified extension' instead of json
|
||||
if self.debug:
|
||||
logging.debug(f"json.loads error {e}")
|
||||
logging.warning(f"error loading json returned by exiftool: {e} {json_str}")
|
||||
return dict()
|
||||
exifdict = exifdict[0]
|
||||
if not tag_groups:
|
||||
@@ -442,25 +414,18 @@ class ExifTool:
|
||||
if normalized:
|
||||
exifdict = {k.lower(): v for (k, v) in exifdict.items()}
|
||||
|
||||
if self.debug:
|
||||
logging.debug(f"asdict: {exifdict}")
|
||||
|
||||
return exifdict
|
||||
|
||||
def json(self):
|
||||
"""returns JSON string containing all EXIF tags and values from exiftool"""
|
||||
json, _, _ = self.run_commands("-json")
|
||||
json = unescape_str(json.decode("utf-8"))
|
||||
if self.debug:
|
||||
logging.debug(f"json: {json}")
|
||||
return json
|
||||
|
||||
def _read_exif(self):
|
||||
"""read exif data from file"""
|
||||
data = self.asdict()
|
||||
self.data = {k: v for k, v in data.items()}
|
||||
if self.debug:
|
||||
logging.debug(f"_read_exif: {self.data}")
|
||||
|
||||
def __str__(self):
|
||||
return f"file: {self.file}\nexiftool: {self._exiftoolproc._exiftool}"
|
||||
@@ -486,17 +451,15 @@ class ExifToolCaching(ExifTool):
|
||||
|
||||
_singletons = {}
|
||||
|
||||
def __new__(cls, filepath, exiftool=None, debug=False):
|
||||
def __new__(cls, filepath, exiftool=None):
|
||||
"""create new object or return instance of already created singleton"""
|
||||
if filepath not in cls._singletons:
|
||||
cls._singletons[filepath] = _ExifToolCaching(
|
||||
filepath, exiftool=exiftool, debug=debug
|
||||
)
|
||||
cls._singletons[filepath] = _ExifToolCaching(filepath, exiftool=exiftool)
|
||||
return cls._singletons[filepath]
|
||||
|
||||
|
||||
class _ExifToolCaching(ExifTool):
|
||||
def __init__(self, filepath, exiftool=None, debug=False):
|
||||
def __init__(self, filepath, exiftool=None):
|
||||
"""Create read-only ExifTool object that caches values
|
||||
|
||||
Args:
|
||||
@@ -506,12 +469,9 @@ class _ExifToolCaching(ExifTool):
|
||||
Returns:
|
||||
ExifTool instance
|
||||
"""
|
||||
self.debug = debug
|
||||
self._json_cache = None
|
||||
self._asdict_cache = {}
|
||||
super().__init__(
|
||||
filepath, exiftool=exiftool, overwrite=False, flags=None, debug=debug
|
||||
)
|
||||
super().__init__(filepath, exiftool=exiftool, overwrite=False, flags=None)
|
||||
|
||||
def run_commands(self, *commands, no_file=False):
|
||||
if commands[0] not in ["-json", "-ver"]:
|
||||
|
||||
@@ -560,11 +560,15 @@ class PhotoExporter:
|
||||
touch_results = []
|
||||
for touch_file in set(touch_files):
|
||||
ts = int(self.photo.date.timestamp())
|
||||
try:
|
||||
stat = os.stat(touch_file)
|
||||
if stat.st_mtime != ts:
|
||||
if not options.dry_run:
|
||||
fileutil.utime(touch_file, (ts, ts))
|
||||
touch_results.append(touch_file)
|
||||
except FileNotFoundError as e:
|
||||
# ignore errors if in dry_run as file may not be present
|
||||
if not options.dry_run:
|
||||
raise e from e
|
||||
return ExportResults(touched=touch_results)
|
||||
|
||||
def _get_edited_filename(self, original_filename):
|
||||
|
||||
@@ -1343,7 +1343,7 @@ class PhotoInfo:
|
||||
try:
|
||||
exiftool_path = self._db._exiftool_path or get_exiftool_path()
|
||||
if self.path is not None and os.path.isfile(self.path):
|
||||
exiftool = ExifToolCaching(self.path, exiftool=exiftool_path, debug=_debug())
|
||||
exiftool = ExifToolCaching(self.path, exiftool=exiftool_path)
|
||||
else:
|
||||
exiftool = None
|
||||
except FileNotFoundError:
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from osxphotos.exiftool import get_exiftool_path
|
||||
|
||||
from osxphotos.exiftool import get_exiftool_path, unescape_str
|
||||
|
||||
TEST_FILE_ONE_KEYWORD = "tests/test-images/wedding.jpg"
|
||||
TEST_FILE_BAD_IMAGE = "tests/test-images/badimage.jpeg"
|
||||
@@ -89,6 +92,20 @@ EXIF_UUID_NO_GROUPS = {
|
||||
}
|
||||
EXIF_UUID_NONE = ["A1DD1F98-2ECD-431F-9AC9-5AFEFE2D3A5C"]
|
||||
|
||||
QUOTED_JSON_BYTES = b'[{"ExifTool:ExifToolVersion": 12.37,"ExifTool:Now": "2022:02:22 18:14:31+00:00","ExifTool:NewGUID": "20220222181431005A76C1A4B4D508A2","ExifTool:FileSequence": 0,"ExifTool:Warning": "Error running "xattr" to extract XAttr tags","ExifTool:ProcessingTime": 0.157028}]'
|
||||
QUOTED_JSON_STRING_UNESCAPED = '[{"ExifTool:ExifToolVersion": 12.37,"ExifTool:Now": "2022:02:22 18:14:31+00:00","ExifTool:NewGUID": "20220222181431005A76C1A4B4D508A2","ExifTool:FileSequence": 0,"ExifTool:Warning": "Error running \\"xattr\\" to extract XAttr tags","ExifTool:ProcessingTime": 0.157028}]'
|
||||
QUOTED_JSON_LOADED = [
|
||||
{
|
||||
"ExifTool:ExifToolVersion": 12.37,
|
||||
"ExifTool:Now": "2022:02:22 18:14:31+00:00",
|
||||
"ExifTool:NewGUID": "20220222181431005A76C1A4B4D508A2",
|
||||
"ExifTool:FileSequence": 0,
|
||||
"ExifTool:Warning": 'Error running "xattr" to extract XAttr tags',
|
||||
"ExifTool:ProcessingTime": 0.157028,
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
try:
|
||||
exiftool = get_exiftool_path()
|
||||
except:
|
||||
@@ -126,6 +143,7 @@ def test_setvalue_1():
|
||||
# test setting a tag value
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -145,6 +163,7 @@ def test_setvalue_multiline():
|
||||
# test setting a tag value with embedded newline
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -164,6 +183,7 @@ def test_setvalue_non_alphanumeric_chars():
|
||||
# test setting a tag value non-alphanumeric characters
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -183,6 +203,7 @@ def test_setvalue_warning():
|
||||
# test setting illegal tag value generates warning
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -199,6 +220,7 @@ def test_setvalue_error():
|
||||
# test setting tag on bad image generates error
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -215,6 +237,7 @@ def test_setvalue_context_manager():
|
||||
# test setting a tag value as context manager
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -241,6 +264,7 @@ def test_setvalue_context_manager_warning():
|
||||
# test setting a tag value as context manager when warning generated
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -257,6 +281,7 @@ def test_setvalue_context_manager_error():
|
||||
# test setting a tag value as context manager when error generated
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -273,6 +298,7 @@ def test_flags():
|
||||
# test that flags work
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -296,6 +322,7 @@ def test_clear_value():
|
||||
# test clearing a tag value
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -315,6 +342,7 @@ def test_addvalues_1():
|
||||
# test setting a tag value
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -332,6 +360,7 @@ def test_addvalues_2():
|
||||
# test setting a tag value where multiple values already exist
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -353,6 +382,7 @@ def test_addvalues_non_alphanumeric_multiline():
|
||||
# test setting a tag value
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -373,6 +403,7 @@ def test_addvalues_unicode():
|
||||
# test setting a tag value with unicode
|
||||
import os.path
|
||||
import tempfile
|
||||
|
||||
import osxphotos.exiftool
|
||||
from osxphotos.fileutil import FileUtil
|
||||
|
||||
@@ -444,9 +475,10 @@ def test_as_dict_no_tag_groups():
|
||||
|
||||
|
||||
def test_json():
|
||||
import osxphotos.exiftool
|
||||
import json
|
||||
|
||||
import osxphotos.exiftool
|
||||
|
||||
exif1 = osxphotos.exiftool.ExifTool(TEST_FILE_ONE_KEYWORD)
|
||||
exifdata = json.loads(exif1.json())
|
||||
assert exifdata[0]["XMP:TagsList"] == "wedding"
|
||||
@@ -498,9 +530,10 @@ def test_photoinfo_exiftool_none():
|
||||
|
||||
def test_exiftool_terminate():
|
||||
"""Test that exiftool process is terminated when exiftool.terminate() is called"""
|
||||
import osxphotos.exiftool
|
||||
import subprocess
|
||||
|
||||
import osxphotos.exiftool
|
||||
|
||||
exif1 = osxphotos.exiftool.ExifTool(TEST_FILE_ONE_KEYWORD)
|
||||
|
||||
ps = subprocess.run(["ps"], capture_output=True)
|
||||
@@ -516,3 +549,11 @@ def test_exiftool_terminate():
|
||||
# verify we can create a new instance after termination
|
||||
exif2 = osxphotos.exiftool.ExifTool(TEST_FILE_ONE_KEYWORD)
|
||||
assert exif2.asdict()["IPTC:Keywords"] == "wedding"
|
||||
|
||||
|
||||
def test_unescape_str():
|
||||
"""Test unescape_str, #636"""
|
||||
quoted_str = unescape_str(QUOTED_JSON_BYTES.decode("utf-8"))
|
||||
assert quoted_str == QUOTED_JSON_STRING_UNESCAPED
|
||||
quoted_json = json.loads(quoted_str)
|
||||
assert quoted_json == QUOTED_JSON_LOADED
|
||||
|
||||
Reference in New Issue
Block a user