Added debug output to exiftool

This commit is contained in:
Rhet Turnbull
2022-02-22 06:40:25 -08:00
parent 5b66962ac1
commit 39ba17dd1c
15 changed files with 92 additions and 45 deletions

View File

@@ -1741,7 +1741,7 @@ Substitution Description
{lf} A line feed: '\n', alias for {newline} {lf} A line feed: '\n', alias for {newline}
{cr} A carriage return: '\r' {cr} A carriage return: '\r'
{crlf} a carriage return + line feed: '\r\n' {crlf} a carriage return + line feed: '\r\n'
{osxphotos_version} The osxphotos version, e.g. '0.46.1' {osxphotos_version} The osxphotos version, e.g. '0.46.2'
{osxphotos_cmd_line} The full command line used to run osxphotos {osxphotos_cmd_line} The full command line used to run osxphotos
The following substitutions may result in multiple values. Thus if specified for 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}| |{lf}|A line feed: '\n', alias for {newline}|
|{cr}|A carriage return: '\r'| |{cr}|A carriage return: '\r'|
|{crlf}|a carriage return + line feed: '\r\n'| |{crlf}|a carriage return + line feed: '\r\n'|
|{osxphotos_version}|The osxphotos version, e.g. '0.46.1'| |{osxphotos_version}|The osxphotos version, e.g. '0.46.2'|
|{osxphotos_cmd_line}|The full command line used to run osxphotos| |{osxphotos_cmd_line}|The full command line used to run osxphotos|
|{album}|Album(s) photo is contained in| |{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| |{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder|

View File

@@ -1,4 +1,4 @@
# Sphinx build info version 1 # 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. # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: d6da9902a4771e5081ae73c361960af8 config: 3bdc7daae06c46fa0e6357e497a27088
tags: 645f666f9bcd5a90fca523b33c5a78b7 tags: 645f666f9bcd5a90fca523b33c5a78b7

View File

@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Overview: module code &#8212; osxphotos 0.46.1 documentation</title> <title>Overview: module code &#8212; osxphotos 0.46.2 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" /> <link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script> <script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>

View File

@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>osxphotos.photosdb.photosdb &#8212; osxphotos 0.46.0 documentation</title> <title>osxphotos.photosdb.photosdb &#8212; osxphotos 0.46.2 documentation</title>
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../../../_static/alabaster.css" /> <link rel="stylesheet" type="text/css" href="../../../_static/alabaster.css" />
<script data-url_root="../../../" id="documentation_options" src="../../../_static/documentation_options.js"></script> <script data-url_root="../../../" id="documentation_options" src="../../../_static/documentation_options.js"></script>
@@ -3312,27 +3312,6 @@
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">to_time</span><span class="p">:</span> <span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">to_time</span><span class="p">:</span>
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">&lt;=</span> <span class="n">options</span><span class="o">.</span><span class="n">to_time</span><span class="p">]</span> <span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">&lt;=</span> <span class="n">options</span><span class="o">.</span><span class="n">to_time</span><span class="p">]</span>
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">burst_photos</span><span class="p">:</span>
<span class="c1"># add the burst_photos to the export set</span>
<span class="n">photos_burst</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">burst</span><span class="p">]</span>
<span class="k">for</span> <span class="n">burst</span> <span class="ow">in</span> <span class="n">photos_burst</span><span class="p">:</span>
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">missing_bursts</span><span class="p">:</span>
<span class="c1"># include burst photos that are missing</span>
<span class="n">photos</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">burst</span><span class="o">.</span><span class="n">burst_photos</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># don&#39;t include missing burst images (these can&#39;t be downloaded with AppleScript)</span>
<span class="n">photos</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">burst</span><span class="o">.</span><span class="n">burst_photos</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">p</span><span class="o">.</span><span class="n">ismissing</span><span class="p">])</span>
<span class="c1"># remove duplicates as each burst photo in the set that&#39;s selected would</span>
<span class="c1"># result in the entire set being added above</span>
<span class="c1"># can&#39;t use set() because PhotoInfo not hashable</span>
<span class="n">seen_uuids</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span><span class="p">:</span>
<span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">uuid</span> <span class="ow">in</span> <span class="n">seen_uuids</span><span class="p">:</span>
<span class="k">continue</span>
<span class="n">seen_uuids</span><span class="p">[</span><span class="n">p</span><span class="o">.</span><span class="n">uuid</span><span class="p">]</span> <span class="o">=</span> <span class="n">p</span>
<span class="n">photos</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">seen_uuids</span><span class="o">.</span><span class="n">values</span><span class="p">())</span>
<span class="k">if</span> <span class="n">name</span><span class="p">:</span> <span class="k">if</span> <span class="n">name</span><span class="p">:</span>
<span class="c1"># search filename fields for text</span> <span class="c1"># search filename fields for text</span>
<span class="c1"># if more than one, find photos with all title values in filename</span> <span class="c1"># if more than one, find photos with all title values in filename</span>
@@ -3483,6 +3462,28 @@
<span class="k">for</span> <span class="n">function</span> <span class="ow">in</span> <span class="n">options</span><span class="o">.</span><span class="n">function</span><span class="p">:</span> <span class="k">for</span> <span class="n">function</span> <span class="ow">in</span> <span class="n">options</span><span class="o">.</span><span class="n">function</span><span class="p">:</span>
<span class="n">photos</span> <span class="o">=</span> <span class="n">function</span><span class="p">[</span><span class="mi">0</span><span class="p">](</span><span class="n">photos</span><span class="p">)</span> <span class="n">photos</span> <span class="o">=</span> <span class="n">function</span><span class="p">[</span><span class="mi">0</span><span class="p">](</span><span class="n">photos</span><span class="p">)</span>
<span class="c1"># burst should be checked last, ref #640</span>
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">burst_photos</span><span class="p">:</span>
<span class="c1"># add the burst_photos to the export set</span>
<span class="n">photos_burst</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">burst</span><span class="p">]</span>
<span class="k">for</span> <span class="n">burst</span> <span class="ow">in</span> <span class="n">photos_burst</span><span class="p">:</span>
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">missing_bursts</span><span class="p">:</span>
<span class="c1"># include burst photos that are missing</span>
<span class="n">photos</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">burst</span><span class="o">.</span><span class="n">burst_photos</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># don&#39;t include missing burst images (these can&#39;t be downloaded with AppleScript)</span>
<span class="n">photos</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">burst</span><span class="o">.</span><span class="n">burst_photos</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">p</span><span class="o">.</span><span class="n">ismissing</span><span class="p">])</span>
<span class="c1"># remove duplicates as each burst photo in the set that&#39;s selected would</span>
<span class="c1"># result in the entire set being added above</span>
<span class="c1"># can&#39;t use set() because PhotoInfo not hashable</span>
<span class="n">seen_uuids</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span><span class="p">:</span>
<span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">uuid</span> <span class="ow">in</span> <span class="n">seen_uuids</span><span class="p">:</span>
<span class="k">continue</span>
<span class="n">seen_uuids</span><span class="p">[</span><span class="n">p</span><span class="o">.</span><span class="n">uuid</span><span class="p">]</span> <span class="o">=</span> <span class="n">p</span>
<span class="n">photos</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">seen_uuids</span><span class="o">.</span><span class="n">values</span><span class="p">())</span>
<span class="k">return</span> <span class="n">photos</span></div> <span class="k">return</span> <span class="n">photos</span></div>
<div class="viewcode-block" id="PhotosDB.execute"><a class="viewcode-back" href="../../../reference.html#osxphotos.PhotosDB.execute">[docs]</a> <span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sql</span><span class="p">):</span> <div class="viewcode-block" id="PhotosDB.execute"><a class="viewcode-back" href="../../../reference.html#osxphotos.PhotosDB.execute">[docs]</a> <span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sql</span><span class="p">):</span>
@@ -3568,7 +3569,6 @@
<h3>Navigation</h3> <h3>Navigation</h3>
<ul> <ul>
<li class="toctree-l1"><a class="reference internal" href="../../../cli.html">osxphotos command line interface (CLI)</a></li> <li class="toctree-l1"><a class="reference internal" href="../../../cli.html">osxphotos command line interface (CLI)</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../modules.html">osxphotos</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../reference.html">osxphotos package</a></li> <li class="toctree-l1"><a class="reference internal" href="../../../reference.html">osxphotos package</a></li>
</ul> </ul>

View File

@@ -1,6 +1,6 @@
var DOCUMENTATION_OPTIONS = { var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '0.46.1', VERSION: '0.46.2',
LANGUAGE: 'None', LANGUAGE: 'None',
COLLAPSE_INDEX: false, COLLAPSE_INDEX: false,
BUILDER: 'html', BUILDER: 'html',

View File

@@ -6,7 +6,7 @@
<meta charset="utf-8" /> <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/" /> <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) &#8212; osxphotos 0.46.1 documentation</title> <title>osxphotos command line interface (CLI) &#8212; osxphotos 0.46.2 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" /> <link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script> <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>

View File

@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Index &#8212; osxphotos 0.46.1 documentation</title> <title>Index &#8212; osxphotos 0.46.2 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" /> <link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script> <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>

View File

@@ -6,7 +6,7 @@
<meta charset="utf-8" /> <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/" /> <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 osxphotoss documentation! &#8212; osxphotos 0.46.1 documentation</title> <title>Welcome to osxphotoss documentation! &#8212; osxphotos 0.46.2 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" /> <link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script> <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>

View File

@@ -6,7 +6,7 @@
<meta charset="utf-8" /> <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/" /> <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 &#8212; osxphotos 0.46.1 documentation</title> <title>osxphotos &#8212; osxphotos 0.46.2 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" /> <link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script> <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>

View File

@@ -6,7 +6,7 @@
<meta charset="utf-8" /> <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/" /> <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 &#8212; osxphotos 0.46.1 documentation</title> <title>osxphotos package &#8212; osxphotos 0.46.2 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" /> <link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script> <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>

View File

@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Search &#8212; osxphotos 0.46.1 documentation</title> <title>Search &#8212; osxphotos 0.46.2 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" /> <link rel="stylesheet" type="text/css" href="_static/alabaster.css" />

View File

@@ -1,3 +1,3 @@
""" version info """ """ version info """
__version__ = "0.46.2" __version__ = "0.46.3"

View File

@@ -2298,6 +2298,9 @@ def help(ctx, topic, **kw):
"This only works if the Photos library being queried is the last-opened (default) library in Photos. " "This only works if the Photos library being queried is the last-opened (default) library in Photos. "
"This feature is currently experimental. I don't know how well it will work on large query sets.", "This feature is currently experimental. I don't know how well it will work on large query sets.",
) )
@click.option(
"--debug", required=False, is_flag=True, default=False, hidden=OSXPHOTOS_HIDDEN
)
@DB_ARGUMENT @DB_ARGUMENT
@click.pass_obj @click.pass_obj
@click.pass_context @click.pass_context
@@ -2382,12 +2385,18 @@ def query(
query_eval, query_eval,
query_function, query_function,
add_to_album, add_to_album,
debug,
): ):
"""Query the Photos database using 1 or more search options; """Query the Photos database using 1 or more search options;
if more than one option is provided, they are treated as "AND" if more than one option is provided, they are treated as "AND"
(e.g. search for photos matching all options). (e.g. search for photos matching all options).
""" """
global DEBUG
if debug:
DEBUG = True
osxphotos._set_debug(True)
# if no query terms, show help and return # if no query terms, show help and return
# sanity check input args # sanity check input args
nonexclusive = [ nonexclusive = [

View File

@@ -103,9 +103,11 @@ class _ExifToolProc:
return cls.instance return cls.instance
def __init__(self, exiftool=None): def __init__(self, exiftool=None, debug=False):
"""construct _ExifToolProc singleton object or return instance of already created object """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)""" 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: if hasattr(self, "_process_running") and self._process_running:
# already running # already running
@@ -115,9 +117,11 @@ class _ExifToolProc:
f"ignoring exiftool={exiftool}" f"ignoring exiftool={exiftool}"
) )
return return
self.debug = debug
self._process_running = False self._process_running = False
self._exiftool = exiftool or get_exiftool_path() self._exiftool = exiftool or get_exiftool_path()
if self.debug:
logging.debug(f"exiftool={self._exiftool}")
self._start_proc() self._start_proc()
@property @property
@@ -167,10 +171,17 @@ class _ExifToolProc:
self._process_running = True self._process_running = True
EXIFTOOL_PROCESSES.append(self) EXIFTOOL_PROCESSES.append(self)
if self.debug:
logging.debug(
"exiftool process started: {self._process} {self._process_running}"
)
def _stop_proc(self): def _stop_proc(self):
"""stop the exiftool process if it's running, otherwise, do nothing""" """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: if not self._process_running:
return return
@@ -190,11 +201,16 @@ class _ExifToolProc:
del self._process del self._process
self._process_running = False self._process_running = False
if self.debug:
logging.debug(f"exiftool process stopped: {self._process}")
class ExifTool: class ExifTool:
"""Basic exiftool interface for reading and writing EXIF tags""" """Basic exiftool interface for reading and writing EXIF tags"""
def __init__(self, filepath, exiftool=None, overwrite=True, flags=None): def __init__(
self, filepath, exiftool=None, overwrite=True, flags=None, debug=False
):
"""Create ExifTool object """Create ExifTool object
Args: Args:
@@ -202,6 +218,7 @@ class ExifTool:
exiftool: path to exiftool, if not specified will look in path exiftool: path to exiftool, if not specified will look in path
overwrite: if True, will overwrite image file without creating backup, default=False 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) 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: Returns:
ExifTool instance ExifTool instance
@@ -209,6 +226,7 @@ class ExifTool:
self.file = filepath self.file = filepath
self.overwrite = overwrite self.overwrite = overwrite
self.flags = flags or [] self.flags = flags or []
self.debug = debug
self.data = {} self.data = {}
self.warning = None self.warning = None
self.error = None self.error = None
@@ -342,6 +360,9 @@ class ExifTool:
+ b"-execute\n" + b"-execute\n"
) )
if self.debug:
logging.debug(f"running exiftool command: {command_str}")
# send the command # send the command
self._process.stdin.write(command_str) self._process.stdin.write(command_str)
self._process.stdin.flush() self._process.stdin.flush()
@@ -362,6 +383,11 @@ class ExifTool:
error = "" if error == b"" else error.decode("utf-8") error = "" if error == b"" else error.decode("utf-8")
self.warning = warning self.warning = warning
self.error = error 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 return output[:-EXIFTOOL_STAYOPEN_EOF_LEN], warning, error
@property @property
@@ -406,18 +432,25 @@ class ExifTool:
if normalized: if normalized:
exifdict = {k.lower(): v for (k, v) in exifdict.items()} exifdict = {k.lower(): v for (k, v) in exifdict.items()}
if self.debug:
logging.debug(f"asdict: {exifdict}")
return exifdict return exifdict
def json(self): def json(self):
"""returns JSON string containing all EXIF tags and values from exiftool""" """returns JSON string containing all EXIF tags and values from exiftool"""
json, _, _ = self.run_commands("-json") json, _, _ = self.run_commands("-json")
json = unescape_str(json.decode("utf-8")) json = unescape_str(json.decode("utf-8"))
if self.debug:
logging.debug(f"json: {json}")
return json return json
def _read_exif(self): def _read_exif(self):
"""read exif data from file""" """read exif data from file"""
data = self.asdict() data = self.asdict()
self.data = {k: v for k, v in data.items()} self.data = {k: v for k, v in data.items()}
if self.debug:
logging.debug(f"_read_exif: {self.data}")
def __str__(self): def __str__(self):
return f"file: {self.file}\nexiftool: {self._exiftoolproc._exiftool}" return f"file: {self.file}\nexiftool: {self._exiftoolproc._exiftool}"
@@ -443,15 +476,17 @@ class ExifToolCaching(ExifTool):
_singletons = {} _singletons = {}
def __new__(cls, filepath, exiftool=None): def __new__(cls, filepath, exiftool=None, debug=False):
"""create new object or return instance of already created singleton""" """create new object or return instance of already created singleton"""
if filepath not in cls._singletons: if filepath not in cls._singletons:
cls._singletons[filepath] = _ExifToolCaching(filepath, exiftool=exiftool) cls._singletons[filepath] = _ExifToolCaching(
filepath, exiftool=exiftool, debug=debug
)
return cls._singletons[filepath] return cls._singletons[filepath]
class _ExifToolCaching(ExifTool): class _ExifToolCaching(ExifTool):
def __init__(self, filepath, exiftool=None): def __init__(self, filepath, exiftool=None, debug=False):
"""Create read-only ExifTool object that caches values """Create read-only ExifTool object that caches values
Args: Args:
@@ -461,9 +496,12 @@ class _ExifToolCaching(ExifTool):
Returns: Returns:
ExifTool instance ExifTool instance
""" """
self.debug = debug
self._json_cache = None self._json_cache = None
self._asdict_cache = {} self._asdict_cache = {}
super().__init__(filepath, exiftool=exiftool, overwrite=False, flags=None) super().__init__(
filepath, exiftool=exiftool, overwrite=False, flags=None, debug=debug
)
def run_commands(self, *commands, no_file=False): def run_commands(self, *commands, no_file=False):
if commands[0] not in ["-json", "-ver"]: if commands[0] not in ["-json", "-ver"]:

View File

@@ -54,7 +54,7 @@ from .scoreinfo import ScoreInfo
from .searchinfo import SearchInfo from .searchinfo import SearchInfo
from .text_detection import detect_text from .text_detection import detect_text
from .uti import get_preferred_uti_extension, get_uti_for_extension from .uti import get_preferred_uti_extension, get_uti_for_extension
from .utils import _debug, _get_resource_loc, list_directory from .utils import _debug, _get_resource_loc, list_directory, _debug
__all__ = ["PhotoInfo", "PhotoInfoNone"] __all__ = ["PhotoInfo", "PhotoInfoNone"]
@@ -1343,7 +1343,7 @@ class PhotoInfo:
try: try:
exiftool_path = self._db._exiftool_path or get_exiftool_path() exiftool_path = self._db._exiftool_path or get_exiftool_path()
if self.path is not None and os.path.isfile(self.path): if self.path is not None and os.path.isfile(self.path):
exiftool = ExifToolCaching(self.path, exiftool=exiftool_path) exiftool = ExifToolCaching(self.path, exiftool=exiftool_path, debug=_debug())
else: else:
exiftool = None exiftool = None
except FileNotFoundError: except FileNotFoundError: