Fix for large files and exiftool, #722

This commit is contained in:
Rhet Turnbull
2022-07-01 08:14:56 -07:00
parent 292fdf3c74
commit 8ac584e708
22 changed files with 78 additions and 67 deletions

View File

@@ -5,7 +5,7 @@
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../genindex.html" /><link rel="search" title="Search" href="../search.html" />
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
<title>Overview: module code - osxphotos 0.50.4 documentation</title>
<title>Overview: module code - osxphotos 0.50.5 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/styles/furo.css?digest=68f4518137b9aefe99b631505a2064c3c42c9852" />
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css" />
@@ -123,7 +123,7 @@
</label>
</div>
<div class="header-center">
<a href="../index.html"><div class="brand">osxphotos 0.50.4 documentation</div></a>
<a href="../index.html"><div class="brand">osxphotos 0.50.5 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -146,7 +146,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="../index.html">
<span class="sidebar-brand-text">osxphotos 0.50.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.50.5 documentation</span>
</a><form class="sidebar-search-container" method="get" action="../search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">

View File

@@ -5,7 +5,7 @@
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
<title>osxphotos.exiftool - osxphotos 0.49.0 documentation</title>
<title>osxphotos.exiftool - osxphotos 0.50.5 documentation</title>
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=68f4518137b9aefe99b631505a2064c3c42c9852" />
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
@@ -123,7 +123,7 @@
</label>
</div>
<div class="header-center">
<a href="../../index.html"><div class="brand">osxphotos 0.49.0 documentation</div></a>
<a href="../../index.html"><div class="brand">osxphotos 0.50.5 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -146,7 +146,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
<span class="sidebar-brand-text">osxphotos 0.49.0 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.50.5 documentation</span>
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
@@ -202,7 +202,9 @@
<span class="sd"> If these aren't important to you, I highly recommend you use Sven Marnach's excellent </span>
<span class="sd"> pyexiftool: https://github.com/smarnach/pyexiftool which provides more functionality """</span>
<span class="kn">import</span> <span class="nn">atexit</span>
<span class="kn">import</span> <span class="nn">contextlib</span>
<span class="kn">import</span> <span class="nn">html</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="kn">import</span> <span class="nn">logging</span>
@@ -300,9 +302,12 @@
<span class="k">return</span> <span class="bp">cls</span><span class="o">.</span><span class="n">instance</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exiftool</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exiftool</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">large_file_support</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
<span class="sd">"""construct _ExifToolProc singleton object or return instance of already created object</span>
<span class="sd"> exiftool: optional path to exiftool binary (if not provided, will search path to find it)</span>
<span class="sd"> Args:</span>
<span class="sd"> exiftool: optional path to exiftool binary (if not provided, will search path to find it)</span>
<span class="sd"> large_file_support: if True, enables large file support (&gt;4GB) via `-api largefilesupport=1`</span>
<span class="sd"> """</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_process_running"</span><span class="p">)</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_process_running</span><span class="p">:</span>
@@ -315,16 +320,14 @@
<span class="k">return</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_process_running</span> <span class="o">=</span> <span class="kc">False</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_exiftool</span> <span class="o">=</span> <span class="n">exiftool</span> <span class="ow">or</span> <span class="n">get_exiftool_path</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_start_proc</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_start_proc</span><span class="p">(</span><span class="n">large_file_support</span><span class="o">=</span><span class="n">large_file_support</span><span class="p">)</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">process</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""return the exiftool subprocess"""</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_process_running</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_process</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_process_running</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_start_proc</span><span class="p">()</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_process</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_process</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">pid</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
@@ -336,7 +339,7 @@
<span class="sd">"""return path to exiftool process"""</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_exiftool</span>
<span class="k">def</span> <span class="nf">_start_proc</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">_start_proc</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">large_file_support</span><span class="p">):</span>
<span class="sd">"""start exiftool in batch mode"""</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_process_running</span><span class="p">:</span>
@@ -347,11 +350,13 @@
<span class="c1"># make sure /usr/bin at start of path so exiftool can find xattr (see #636)</span>
<span class="n">env</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
<span class="n">env</span><span class="p">[</span><span class="s2">"PATH"</span><span class="p">]</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">'/usr/bin/:</span><span class="si">{</span><span class="n">env</span><span class="p">[</span><span class="s2">"PATH"</span><span class="p">]</span><span class="si">}</span><span class="s1">'</span>
<span class="n">large_file_args</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"-api"</span><span class="p">,</span> <span class="s2">"largefilesupport=1"</span><span class="p">]</span> <span class="k">if</span> <span class="n">large_file_support</span> <span class="k">else</span> <span class="p">[]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span>
<span class="p">[</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_exiftool</span><span class="p">,</span>
<span class="s2">"-stay_open"</span><span class="p">,</span> <span class="c1"># keep process open in batch mode</span>
<span class="s2">"True"</span><span class="p">,</span> <span class="c1"># -stay_open=True, keep process open in batch mode</span>
<span class="o">*</span><span class="n">large_file_args</span><span class="p">,</span>
<span class="s2">"-@"</span><span class="p">,</span> <span class="c1"># read command-line arguments from file</span>
<span class="s2">"-"</span><span class="p">,</span> <span class="c1"># read from stdin</span>
<span class="s2">"-common_args"</span><span class="p">,</span> <span class="c1"># specifies args common to all commands subsequently run</span>
@@ -375,13 +380,10 @@
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_process_running</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">with</span> <span class="n">contextlib</span><span class="o">.</span><span class="n">suppress</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_process</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="sa">b</span><span class="s2">"-stay_open</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_process</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="sa">b</span><span class="s2">"False</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_process</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_process</span><span class="o">.</span><span class="n">communicate</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span>
<span class="k">except</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">TimeoutExpired</span><span class="p">:</span>
@@ -395,7 +397,14 @@
<div class="viewcode-block" id="ExifTool"><a class="viewcode-back" href="../../reference.html#osxphotos.ExifTool">[docs]</a><span class="k">class</span> <span class="nc">ExifTool</span><span class="p">:</span>
<span class="sd">"""Basic exiftool interface for reading and writing EXIF tags"""</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filepath</span><span class="p">,</span> <span class="n">exiftool</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">overwrite</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">flags</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">filepath</span><span class="p">,</span>
<span class="n">exiftool</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">overwrite</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">flags</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">large_file_support</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="p">):</span>
<span class="sd">"""Create ExifTool object</span>
<span class="sd"> Args:</span>
@@ -403,6 +412,7 @@
<span class="sd"> exiftool: path to exiftool, if not specified will look in path</span>
<span class="sd"> overwrite: if True, will overwrite image file without creating backup, default=False</span>
<span class="sd"> flags: optional list of exiftool flags to prepend to exiftool command when writing metadata (e.g. -m or -F)</span>
<span class="sd"> large_file_support: if True, enables large file support in exiftool (`-api largefilesupport=1`)</span>
<span class="sd"> Returns:</span>
<span class="sd"> ExifTool instance</span>
@@ -415,7 +425,9 @@
<span class="bp">self</span><span class="o">.</span><span class="n">error</span> <span class="o">=</span> <span class="kc">None</span>
<span class="c1"># if running as a context manager, self._context_mgr will be True</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_context_mgr</span> <span class="o">=</span> <span class="kc">False</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_exiftoolproc</span> <span class="o">=</span> <span class="n">_ExifToolProc</span><span class="p">(</span><span class="n">exiftool</span><span class="o">=</span><span class="n">exiftool</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_exiftoolproc</span> <span class="o">=</span> <span class="n">_ExifToolProc</span><span class="p">(</span>
<span class="n">exiftool</span><span class="o">=</span><span class="n">exiftool</span><span class="p">,</span> <span class="n">large_file_support</span><span class="o">=</span><span class="n">large_file_support</span>
<span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_read_exif</span><span class="p">()</span>
<span class="nd">@property</span>
@@ -523,7 +535,7 @@
<span class="n">commands</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">commands</span><span class="p">)</span>
<span class="n">commands</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">"-overwrite_original"</span><span class="p">)</span>
<span class="n">filename</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">fsencode</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">file</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">no_file</span> <span class="k">else</span> <span class="sa">b</span><span class="s2">""</span>
<span class="n">filename</span> <span class="o">=</span> <span class="sa">b</span><span class="s2">""</span> <span class="k">if</span> <span class="n">no_file</span> <span class="k">else</span> <span class="n">os</span><span class="o">.</span><span class="n">fsencode</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">file</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">flags</span><span class="p">:</span>
<span class="c1"># need to split flags, e.g. so "--ext AVI" becomes ["--ext", "AVI"]</span>
@@ -619,8 +631,7 @@
<span class="k">def</span> <span class="nf">_read_exif</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""read exif data from file"""</span>
<span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">asdict</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="n">v</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">data</span><span class="o">.</span><span class="n">items</span><span class="p">()}</span>
<span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">asdict</span><span class="p">()</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="sa">f</span><span class="s2">"file: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">file</span><span class="si">}</span><span class="se">\n</span><span class="s2">exiftool: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_exiftoolproc</span><span class="o">.</span><span class="n">_exiftool</span><span class="si">}</span><span class="s2">"</span>

View File

@@ -5,7 +5,7 @@
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
<title>osxphotos.photoexporter - osxphotos 0.50.1 documentation</title>
<title>osxphotos.photoexporter - osxphotos 0.50.5 documentation</title>
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=68f4518137b9aefe99b631505a2064c3c42c9852" />
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
@@ -123,7 +123,7 @@
</label>
</div>
<div class="header-center">
<a href="../../index.html"><div class="brand">osxphotos 0.50.1 documentation</div></a>
<a href="../../index.html"><div class="brand">osxphotos 0.50.5 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -146,7 +146,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
<span class="sidebar-brand-text">osxphotos 0.50.1 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.50.5 documentation</span>
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">