Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abbb200838 | ||
|
|
e7eefce5c5 | ||
|
|
2ed6e11426 | ||
|
|
4096054abb | ||
|
|
5ab5c53b26 | ||
|
|
35a4777ae4 | ||
|
|
9fddbefa66 | ||
|
|
ff2e810d49 | ||
|
|
026e90a8ed | ||
|
|
95103f7c8d |
@@ -1943,7 +1943,7 @@ cog.out(get_template_field_table())
|
||||
|{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.48.3'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.48.6'|
|
||||
|{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|
|
||||
|
||||
26
CHANGELOG.md
26
CHANGELOG.md
@@ -4,6 +4,32 @@ All notable changes to this project will be documented in this file. Dates are d
|
||||
|
||||
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
|
||||
#### [v0.48.6](https://github.com/RhetTbull/osxphotos/compare/v0.48.5...v0.48.6)
|
||||
|
||||
> 7 May 2022
|
||||
|
||||
- Added --limit, version bump [`5ab5c53`](https://github.com/RhetTbull/osxphotos/commit/5ab5c53b26207eb326191c110ac544592c980c32)
|
||||
|
||||
#### [v0.48.5](https://github.com/RhetTbull/osxphotos/compare/v0.48.4...v0.48.5)
|
||||
|
||||
> 7 May 2022
|
||||
|
||||
- Added --limit, #592 [`#685`](https://github.com/RhetTbull/osxphotos/pull/685)
|
||||
|
||||
#### [v0.48.4](https://github.com/RhetTbull/osxphotos/compare/v0.48.3...v0.48.4)
|
||||
|
||||
> 6 May 2022
|
||||
|
||||
- Feature metadata changed 621 [`#684`](https://github.com/RhetTbull/osxphotos/pull/684)
|
||||
- Version bump, updated docs [`ff2e810`](https://github.com/RhetTbull/osxphotos/commit/ff2e810d49f9acffb81f3b7aea6271191d6762f9)
|
||||
|
||||
#### [v0.48.3](https://github.com/RhetTbull/osxphotos/compare/v0.48.2...v0.48.3)
|
||||
|
||||
> 5 May 2022
|
||||
|
||||
- Added --added-after, --added-before, --added-in-last, #439 [`#683`](https://github.com/RhetTbull/osxphotos/pull/683)
|
||||
- Updated to pytimeparse2, added tests for custom Click param types [`3ed658a`](https://github.com/RhetTbull/osxphotos/commit/3ed658a7d018b5ac61c1054e20a59576e8613609)
|
||||
|
||||
#### [v0.48.2](https://github.com/RhetTbull/osxphotos/compare/v0.48.1...v0.48.2)
|
||||
|
||||
> 3 May 2022
|
||||
|
||||
11
README.md
11
README.md
@@ -882,6 +882,9 @@ Options:
|
||||
exported files, even if missing from the
|
||||
export folder and only exports new files that
|
||||
haven't previously been exported.
|
||||
--limit LIMIT Export at most LIMIT photos. Useful for
|
||||
testing. May be used with --update to export
|
||||
incrementally.
|
||||
--dry-run Dry run (test) the export but don't actually
|
||||
export any files; most useful with --verbose.
|
||||
--export-as-hardlink Hardlink files instead of copying them. Cannot
|
||||
@@ -1831,7 +1834,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.48.3'
|
||||
{osxphotos_version} The osxphotos version, e.g. '0.48.6'
|
||||
{osxphotos_cmd_line} The full command line used to run osxphotos
|
||||
|
||||
The following substitutions may result in multiple values. Thus if specified
|
||||
@@ -2981,6 +2984,9 @@ Returns a [ScoreInfo](#scoreinfo) data class object which provides access to the
|
||||
|
||||
Returns list of PhotoInfo objects for *possible* duplicates or empty list if no matching duplicates. Photos are considered possible duplicates if the photo's original file size, date created, height, and width match another those of another photo. This does not do a byte-for-byte comparison or compute a hash which makes it fast and allows for identification of possible duplicates even if originals are not downloaded from iCloud. The signature-based approach should be robust enough to match duplicates created either through the "duplicate photo" menu item or imported twice into the library but you should not rely on this 100% for identification of all duplicates.
|
||||
|
||||
#### `hexdigest`
|
||||
Returns a unique digest of the photo's properties and metadata; useful for detecting changes in any property/metadata of the photo.
|
||||
|
||||
#### `json()`
|
||||
|
||||
Returns a JSON representation of all photo info.
|
||||
@@ -3994,7 +4000,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.48.3'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.48.6'|
|
||||
|{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|
|
||||
@@ -4174,6 +4180,7 @@ Attributes:
|
||||
* exiftool_error: list of errors generated by exiftool during export
|
||||
* xattr_written: list of files with extended attributes written during export
|
||||
* xattr_skipped: list of files where extended attributes were skipped when update=True
|
||||
* metadata_changed: list of files where metadata changed since last export
|
||||
* deleted_files: reserved for use by osxphotos CLI
|
||||
* deleted_directories: reserved for use by osxphotos CLI
|
||||
* exported_album: reserved for use by osxphotos CLI
|
||||
|
||||
@@ -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: 7bb2c9249a5178c80045917234b5db0f
|
||||
config: 7c9b3fd4a18d08287a7ba12c4e147bf5
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
|
||||
@@ -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.48.3 documentation</title>
|
||||
<title>Overview: module code - osxphotos 0.48.6 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.48.3 documentation</div></a>
|
||||
<a href="../index.html"><div class="brand">osxphotos 0.48.6 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.48.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.6 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">
|
||||
|
||||
@@ -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.47.9 documentation</title>
|
||||
<title>osxphotos.photoexporter - osxphotos 0.48.3 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.47.9 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.48.3 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.47.9 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.3 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">
|
||||
@@ -155,11 +155,12 @@
|
||||
</form>
|
||||
<div id="searchbox"></div><div class="sidebar-scroll"><div class="sidebar-tree">
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../overview.html">osxphotos</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../tutorial.html">osxphotos Tutorial</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="../../package_overview.html">Example uses of the python package</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">osxphotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../overview.html">OSXPhotos</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../tutorial.html">OSXPhotos Tutorial</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="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -197,13 +198,11 @@
|
||||
<span class="sd">"""</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">dataclasses</span>
|
||||
<span class="kn">import</span> <span class="nn">hashlib</span>
|
||||
<span class="kn">import</span> <span class="nn">json</span>
|
||||
<span class="kn">import</span> <span class="nn">logging</span>
|
||||
<span class="kn">import</span> <span class="nn">os</span>
|
||||
<span class="kn">import</span> <span class="nn">pathlib</span>
|
||||
<span class="kn">import</span> <span class="nn">re</span>
|
||||
<span class="kn">import</span> <span class="nn">tempfile</span>
|
||||
<span class="kn">import</span> <span class="nn">typing</span> <span class="k">as</span> <span class="nn">t</span>
|
||||
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span> <span class="c1"># pylint: disable=syntax-error</span>
|
||||
<span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">asdict</span><span class="p">,</span> <span class="n">dataclass</span>
|
||||
@@ -240,14 +239,13 @@
|
||||
<span class="kn">from</span> <span class="nn">.phototemplate</span> <span class="kn">import</span> <span class="n">RenderOptions</span>
|
||||
<span class="kn">from</span> <span class="nn">.rich_utils</span> <span class="kn">import</span> <span class="n">add_rich_markup_tag</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="kn">from</span> <span class="nn">.utils</span> <span class="kn">import</span> <span class="n">increment_filename</span><span class="p">,</span> <span class="n">lineno</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">hexdigest</span><span class="p">,</span> <span class="n">increment_filename</span><span class="p">,</span> <span class="n">lineno</span><span class="p">,</span> <span class="n">list_directory</span>
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="s2">"ExportError"</span><span class="p">,</span>
|
||||
<span class="s2">"ExportOptions"</span><span class="p">,</span>
|
||||
<span class="s2">"ExportResults"</span><span class="p">,</span>
|
||||
<span class="s2">"PhotoExporter"</span><span class="p">,</span>
|
||||
<span class="s2">"hexdigest"</span><span class="p">,</span>
|
||||
<span class="s2">"rename_jpeg_files"</span><span class="p">,</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
@@ -461,6 +459,7 @@
|
||||
<span class="n">exported_album</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">skipped_album</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">missing_album</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">metadata_changed</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">exported</span> <span class="o">=</span> <span class="n">exported</span> <span class="ow">or</span> <span class="p">[]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">new</span> <span class="o">=</span> <span class="n">new</span> <span class="ow">or</span> <span class="p">[]</span>
|
||||
@@ -487,6 +486,7 @@
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">exported_album</span> <span class="o">=</span> <span class="n">exported_album</span> <span class="ow">or</span> <span class="p">[]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">skipped_album</span> <span class="o">=</span> <span class="n">skipped_album</span> <span class="ow">or</span> <span class="p">[]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">missing_album</span> <span class="o">=</span> <span class="n">missing_album</span> <span class="ow">or</span> <span class="p">[]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">metadata_changed</span> <span class="o">=</span> <span class="n">metadata_changed</span> <span class="ow">or</span> <span class="p">[]</span>
|
||||
|
||||
<div class="viewcode-block" id="ExportResults.all_files"><a class="viewcode-back" href="../../reference.html#osxphotos.ExportResults.all_files">[docs]</a> <span class="k">def</span> <span class="nf">all_files</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""return all filenames contained in results"""</span>
|
||||
@@ -537,6 +537,7 @@
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">exported_album</span> <span class="o">+=</span> <span class="n">other</span><span class="o">.</span><span class="n">exported_album</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">skipped_album</span> <span class="o">+=</span> <span class="n">other</span><span class="o">.</span><span class="n">skipped_album</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">missing_album</span> <span class="o">+=</span> <span class="n">other</span><span class="o">.</span><span class="n">missing_album</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">metadata_changed</span> <span class="o">+=</span> <span class="n">other</span><span class="o">.</span><span class="n">metadata_changed</span>
|
||||
|
||||
<span class="k">return</span> <span class="bp">self</span>
|
||||
|
||||
@@ -566,12 +567,14 @@
|
||||
<span class="o">+</span> <span class="sa">f</span><span class="s2">",exported_album=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">exported_album</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="o">+</span> <span class="sa">f</span><span class="s2">",skipped_album=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">skipped_album</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="o">+</span> <span class="sa">f</span><span class="s2">",missing_album=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">missing_album</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="o">+</span> <span class="sa">f</span><span class="s2">",metadata_changed=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">metadata_changed</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="o">+</span> <span class="s2">")"</span>
|
||||
<span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="PhotoExporter"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoExporter">[docs]</a><span class="k">class</span> <span class="nc">PhotoExporter</span><span class="p">:</span>
|
||||
<span class="sd">"""Export a photo"""</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">photo</span><span class="p">:</span> <span class="s2">"PhotoInfo"</span><span class="p">,</span> <span class="n">tmpdir</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">photo</span> <span class="o">=</span> <span class="n">photo</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_render_options</span> <span class="o">=</span> <span class="n">RenderOptions</span><span class="p">()</span>
|
||||
@@ -934,7 +937,7 @@
|
||||
<span class="k">return</span> <span class="n">ShouldUpdate</span><span class="o">.</span><span class="n">EDITED_SIG_DIFFERENT</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">force_update</span><span class="p">:</span>
|
||||
<span class="n">current_digest</span> <span class="o">=</span> <span class="n">hexdigest</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">json</span><span class="p">())</span>
|
||||
<span class="n">current_digest</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">hexdigest</span>
|
||||
<span class="k">if</span> <span class="n">current_digest</span> <span class="o">!=</span> <span class="n">file_record</span><span class="o">.</span><span class="n">digest</span><span class="p">:</span>
|
||||
<span class="c1"># metadata in Photos changed, force update</span>
|
||||
<span class="k">return</span> <span class="n">ShouldUpdate</span><span class="o">.</span><span class="n">DIGEST_DIFFERENT</span>
|
||||
@@ -1374,8 +1377,9 @@
|
||||
<span class="n">rec</span><span class="o">.</span><span class="n">dest_sig</span> <span class="o">=</span> <span class="n">fileutil</span><span class="o">.</span><span class="n">file_sig</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">exiftool</span><span class="p">:</span>
|
||||
<span class="n">rec</span><span class="o">.</span><span class="n">exifdata</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_exiftool_json_sidecar</span><span class="p">(</span><span class="n">options</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">force_update</span><span class="p">:</span>
|
||||
<span class="n">rec</span><span class="o">.</span><span class="n">digest</span> <span class="o">=</span> <span class="n">hexdigest</span><span class="p">(</span><span class="n">photoinfo</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">hexdigest</span> <span class="o">!=</span> <span class="n">rec</span><span class="o">.</span><span class="n">digest</span><span class="p">:</span>
|
||||
<span class="n">results</span><span class="o">.</span><span class="n">metadata_changed</span> <span class="o">=</span> <span class="p">[</span><span class="n">dest_str</span><span class="p">]</span>
|
||||
<span class="n">rec</span><span class="o">.</span><span class="n">digest</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">hexdigest</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">results</span>
|
||||
|
||||
@@ -2206,13 +2210,6 @@
|
||||
<span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span></div>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">hexdigest</span><span class="p">(</span><span class="n">strval</span><span class="p">):</span>
|
||||
<span class="sd">"""hexdigest of a string, using blake2b"""</span>
|
||||
<span class="n">h</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">blake2b</span><span class="p">(</span><span class="n">digest_size</span><span class="o">=</span><span class="mi">20</span><span class="p">)</span>
|
||||
<span class="n">h</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">strval</span><span class="p">,</span> <span class="s2">"utf-8"</span><span class="p">))</span>
|
||||
<span class="k">return</span> <span class="n">h</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">_check_export_suffix</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">dest</span><span class="p">,</span> <span class="n">edited</span><span class="p">):</span>
|
||||
<span class="sd">"""Helper function for exporting photos to check file extensions of destination path.</span>
|
||||
|
||||
|
||||
@@ -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.photoinfo - osxphotos 0.48.1 documentation</title>
|
||||
<title>osxphotos.photoinfo - osxphotos 0.48.3 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.48.1 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.48.3 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.48.1 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.3 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">
|
||||
@@ -207,6 +207,7 @@
|
||||
<span class="kn">import</span> <span class="nn">os.path</span>
|
||||
<span class="kn">import</span> <span class="nn">pathlib</span>
|
||||
<span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">timedelta</span><span class="p">,</span> <span class="n">timezone</span>
|
||||
<span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="n">cached_property</span>
|
||||
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Optional</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">yaml</span>
|
||||
@@ -250,7 +251,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">_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">_get_resource_loc</span><span class="p">,</span> <span class="n">hexdigest</span><span class="p">,</span> <span class="n">list_directory</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>
|
||||
|
||||
@@ -1552,6 +1553,12 @@
|
||||
<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="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_exiftool</span>
|
||||
|
||||
<span class="nd">@cached_property</span>
|
||||
<span class="k">def</span> <span class="nf">hexdigest</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns a unique digest of the photo's properties and metadata;</span>
|
||||
<span class="sd"> useful for detecting changes in any property/metadata of the photo"""</span>
|
||||
<span class="k">return</span> <span class="n">hexdigest</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">json</span><span class="p">())</span>
|
||||
|
||||
<div class="viewcode-block" id="PhotoInfo.detected_text"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoInfo.detected_text">[docs]</a> <span class="k">def</span> <span class="nf">detected_text</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">confidence_threshold</span><span class="o">=</span><span class="n">TEXT_DETECTION_CONFIDENCE_THRESHOLD</span><span class="p">):</span>
|
||||
<span class="sd">"""Detects text in photo and returns lists of results as (detected text, confidence)</span>
|
||||
|
||||
|
||||
@@ -320,7 +320,7 @@ Template Substitutions
|
||||
* - {crlf}
|
||||
- a carriage return + line feed: '\r\n'
|
||||
* - {osxphotos_version}
|
||||
- The osxphotos version, e.g. '0.48.3'
|
||||
- The osxphotos version, e.g. '0.48.6'
|
||||
* - {osxphotos_cmd_line}
|
||||
- The full command line used to run osxphotos
|
||||
* - {album}
|
||||
|
||||
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.48.3',
|
||||
VERSION: '0.48.6',
|
||||
LANGUAGE: 'None',
|
||||
COLLAPSE_INDEX: false,
|
||||
BUILDER: 'html',
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos Template System" href="template_help.html" /><link rel="prev" title="OSXPhotos Tutorial" href="tutorial.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
|
||||
<title>OSXPhotos Command Line Interface (CLI) - osxphotos 0.48.3 documentation</title>
|
||||
<title>OSXPhotos Command Line Interface (CLI) - osxphotos 0.48.6 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" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.6 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.6 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">
|
||||
@@ -765,6 +765,11 @@ to modify this behavior.</p>
|
||||
<dd><p>If used with –update, ignores any previously exported files, even if missing from the export folder and only exports new files that haven’t previously been exported.</p>
|
||||
</dd></dl>
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-limit">
|
||||
<span class="sig-name descname"><span class="pre">--limit</span></span><span class="sig-prename descclassname"> <span class="pre"><LIMIT></span></span><a class="headerlink" href="#cmdoption-osxphotos-export-limit" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Export at most LIMIT photos. Useful for testing. Maybe used with –update to export incrementally.</p>
|
||||
</dd></dl>
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-dry-run">
|
||||
<span class="sig-name descname"><span class="pre">--dry-run</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-export-dry-run" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Dry run (test) the export but don’t actually export any files; most useful with –verbose.</p>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="#" /><link rel="search" title="Search" href="search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/><title>Index - osxphotos 0.48.3 documentation</title>
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/><title>Index - osxphotos 0.48.6 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" />
|
||||
@@ -122,7 +122,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.6 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -145,7 +145,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.6 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">
|
||||
@@ -877,6 +877,13 @@
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-timewarp-L">osxphotos-timewarp command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
--limit
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-limit">osxphotos-export command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
@@ -2335,6 +2342,8 @@
|
||||
</li>
|
||||
</ul></li>
|
||||
<li><a href="reference.html#osxphotos.PhotoInfo.height">height (osxphotos.PhotoInfo property)</a>
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.PhotoInfo.hexdigest">hexdigest (osxphotos.PhotoInfo property)</a>
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.PhotoInfo.hidden">hidden (osxphotos.PhotoInfo property)</a>
|
||||
|
||||
@@ -2799,6 +2808,8 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-keyword-template">--keyword-template</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-label">--label</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-limit">--limit</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-live">--live</a>
|
||||
</li>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos" href="overview.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
|
||||
<title>osxphotos 0.48.3 documentation</title>
|
||||
<title>osxphotos 0.48.6 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" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="#"><div class="brand">osxphotos 0.48.3 documentation</div></a>
|
||||
<a href="#"><div class="brand">osxphotos 0.48.6 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="#">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.6 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">
|
||||
|
||||
BIN
docs/objects.inv
BIN
docs/objects.inv
Binary file not shown.
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos Tutorial" href="tutorial.html" /><link rel="prev" title="Welcome to OSXPhotos’s documentation!" href="index.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
|
||||
<title>OSXPhotos - osxphotos 0.48.3 documentation</title>
|
||||
<title>OSXPhotos - osxphotos 0.48.6 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" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.6 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.6 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">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos python API" href="reference.html" /><link rel="prev" title="OSXPhotos Template System" href="template_help.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
|
||||
<title>OSXPhotos Python Package Overview - osxphotos 0.48.3 documentation</title>
|
||||
<title>OSXPhotos Python Package Overview - osxphotos 0.48.6 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" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.6 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.6 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">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<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>Python Module Index - osxphotos 0.48.3 documentation</title>
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/><title>Python Module Index - osxphotos 0.48.6 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" />
|
||||
@@ -122,7 +122,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.6 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -145,7 +145,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.6 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">
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="#" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/><title>Search - osxphotos 0.48.3 documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/><title>Search - osxphotos 0.48.6 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" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||
@@ -121,7 +121,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.6 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -144,7 +144,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.6 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="#" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos Python Package Overview" href="package_overview.html" /><link rel="prev" title="OSXPhotos Command Line Interface (CLI)" href="cli.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
|
||||
<title>OSXPhotos Template System - osxphotos 0.48.3 documentation</title>
|
||||
<title>OSXPhotos Template System - osxphotos 0.48.6 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" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.6 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.6 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">
|
||||
@@ -567,7 +567,7 @@
|
||||
<td><p>a carriage return + line feed: ‘rn’</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{osxphotos_version}</p></td>
|
||||
<td><p>The osxphotos version, e.g. ‘0.48.3’</p></td>
|
||||
<td><p>The osxphotos version, e.g. ‘0.48.6’</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{osxphotos_cmd_line}</p></td>
|
||||
<td><p>The full command line used to run osxphotos</p></td>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos Command Line Interface (CLI)" href="cli.html" /><link rel="prev" title="OSXPhotos" href="overview.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
|
||||
<title>OSXPhotos Tutorial - osxphotos 0.48.3 documentation</title>
|
||||
<title>OSXPhotos Tutorial - osxphotos 0.48.6 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" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.48.6 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.6 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">
|
||||
|
||||
@@ -320,7 +320,7 @@ Template Substitutions
|
||||
* - {crlf}
|
||||
- a carriage return + line feed: '\r\n'
|
||||
* - {osxphotos_version}
|
||||
- The osxphotos version, e.g. '0.48.3'
|
||||
- The osxphotos version, e.g. '0.48.6'
|
||||
* - {osxphotos_cmd_line}
|
||||
- The full command line used to run osxphotos
|
||||
* - {album}
|
||||
|
||||
@@ -50,6 +50,7 @@ def post_function(
|
||||
# exported_album: list of tuples of (filename, album_name) for exported files added to album with --add-exported-to-album
|
||||
# skipped_album: list of tuples of (filename, album_name) for skipped files added to album with --add-skipped-to-album
|
||||
# missing_album: list of tuples of (filename, album_name) for missing files added to album with --add-missing-to-album
|
||||
# metadata_changed: list of filenames that had metadata changes since last export
|
||||
|
||||
for filename in results.exported:
|
||||
# do your processing here
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.48.3"
|
||||
__version__ = "0.48.6"
|
||||
|
||||
@@ -146,6 +146,11 @@ def QUERY_OPTIONS(f):
|
||||
help="Search for photos with keyword KEYWORD. "
|
||||
'If more than one keyword, treated as "OR", e.g. find photos matching any keyword',
|
||||
),
|
||||
o(
|
||||
"--no-keyword",
|
||||
is_flag=True,
|
||||
help="Search for photos with no keyword.",
|
||||
),
|
||||
o(
|
||||
"--person",
|
||||
metavar="PERSON",
|
||||
|
||||
@@ -55,7 +55,7 @@ from osxphotos.photosalbum import PhotosAlbum
|
||||
from osxphotos.phototemplate import PhotoTemplate, RenderOptions
|
||||
from osxphotos.queryoptions import QueryOptions
|
||||
from osxphotos.uti import get_preferred_uti_extension
|
||||
from osxphotos.utils import format_sec_to_hhmmss, normalize_fs_path
|
||||
from osxphotos.utils import format_sec_to_hhmmss, normalize_fs_path, pluralize
|
||||
|
||||
from .click_rich_echo import (
|
||||
rich_click_echo,
|
||||
@@ -138,6 +138,13 @@ from .verbose import get_verbose_console, time_stamp, verbose_print
|
||||
help="If used with --update, ignores any previously exported files, even if missing from "
|
||||
"the export folder and only exports new files that haven't previously been exported.",
|
||||
)
|
||||
@click.option(
|
||||
"--limit",
|
||||
metavar="LIMIT",
|
||||
help="Export at most LIMIT photos. "
|
||||
"Useful for testing. May be used with --update to export incrementally.",
|
||||
type=int,
|
||||
)
|
||||
@click.option(
|
||||
"--dry-run",
|
||||
is_flag=True,
|
||||
@@ -730,6 +737,7 @@ def export(
|
||||
keyword_template,
|
||||
keyword,
|
||||
label,
|
||||
limit,
|
||||
live,
|
||||
load_config,
|
||||
location,
|
||||
@@ -741,6 +749,7 @@ def export(
|
||||
no_description,
|
||||
no_likes,
|
||||
no_location,
|
||||
no_keyword,
|
||||
no_place,
|
||||
no_progress,
|
||||
no_title,
|
||||
@@ -945,6 +954,7 @@ def export(
|
||||
keyword = cfg.keyword
|
||||
keyword_template = cfg.keyword_template
|
||||
label = cfg.label
|
||||
limit = cfg.limit
|
||||
live = cfg.live
|
||||
location = cfg.location
|
||||
max_size = cfg.max_size
|
||||
@@ -955,6 +965,7 @@ def export(
|
||||
no_description = cfg.no_description
|
||||
no_likes = cfg.no_likes
|
||||
no_location = cfg.no_location
|
||||
no_keyword = cfg.no_keyword
|
||||
no_place = cfg.no_place
|
||||
no_progress = cfg.no_progress
|
||||
no_title = cfg.no_title
|
||||
@@ -1059,6 +1070,7 @@ def export(
|
||||
("in_album", "not_in_album"),
|
||||
("live", "not_live"),
|
||||
("location", "no_location"),
|
||||
("keyword", "no_keyword"),
|
||||
("only_photos", "only_movies"),
|
||||
("panorama", "not_panorama"),
|
||||
("place", "no_place"),
|
||||
@@ -1316,6 +1328,7 @@ def export(
|
||||
no_description=no_description,
|
||||
no_likes=no_likes,
|
||||
no_location=no_location,
|
||||
no_keyword=no_keyword,
|
||||
no_place=no_place,
|
||||
no_title=no_title,
|
||||
not_burst=not_burst,
|
||||
@@ -1383,8 +1396,7 @@ def export(
|
||||
|
||||
if photos:
|
||||
num_photos = len(photos)
|
||||
# TODO: photos or photo appears several times, pull into a separate function
|
||||
photo_str = "photos" if num_photos > 1 else "photo"
|
||||
photo_str = pluralize(num_photos, "photo", "photos")
|
||||
rich_echo(
|
||||
f"Exporting [num]{num_photos}[/num] {photo_str} to [filepath]{dest}[/]..."
|
||||
)
|
||||
@@ -1412,9 +1424,11 @@ def export(
|
||||
)
|
||||
|
||||
photo_num = 0
|
||||
num_exported = 0
|
||||
limit_str = f" (limit = [num]{limit}[/num])" if limit else ""
|
||||
with rich_progress(console=get_verbose_console(), mock=no_progress) as progress:
|
||||
task = progress.add_task(
|
||||
f"Exporting [num]{num_photos}[/] photos", total=num_photos
|
||||
f"Exporting [num]{num_photos}[/] photos{limit_str}", total=num_photos
|
||||
)
|
||||
for p in photos:
|
||||
photo_num += 1
|
||||
@@ -1579,7 +1593,17 @@ def export(
|
||||
|
||||
progress.advance(task)
|
||||
|
||||
photo_str_total = "photos" if len(photos) != 1 else "photo"
|
||||
# handle limit
|
||||
if export_results.exported:
|
||||
# if any photos were exported, increment num_exported used by limit
|
||||
# limit considers each PhotoInfo object as a single photo even if multiple files are exported
|
||||
num_exported += 1
|
||||
if limit and num_exported >= limit:
|
||||
# advance progress to end
|
||||
progress.advance(task, num_photos - photo_num)
|
||||
break
|
||||
|
||||
photo_str_total = pluralize(len(photos), "photo", "photos")
|
||||
if update or force_update:
|
||||
summary = (
|
||||
f"Processed: [num]{len(photos)}[/] {photo_str_total}, "
|
||||
@@ -1597,6 +1621,8 @@ def export(
|
||||
summary += f"error: [num]{len(results.error)}[/]"
|
||||
if touch_file:
|
||||
summary += f", touched date: [num]{len(results.touched)}[/]"
|
||||
if limit:
|
||||
summary += f", limit: [num]{num_exported}[/]/[num]{limit}[/] exported"
|
||||
rich_echo(summary)
|
||||
stop_time = time.perf_counter()
|
||||
rich_echo(f"Elapsed time: [time]{format_sec_to_hhmmss(stop_time-start_time)}")
|
||||
|
||||
@@ -113,6 +113,7 @@ def query(
|
||||
no_description,
|
||||
no_likes,
|
||||
no_location,
|
||||
no_keyword,
|
||||
no_place,
|
||||
no_title,
|
||||
not_burst,
|
||||
@@ -197,6 +198,7 @@ def query(
|
||||
(any(description), no_description),
|
||||
(any(place), no_place),
|
||||
(any(title), no_title),
|
||||
(any(keyword), no_keyword),
|
||||
(burst, not_burst),
|
||||
(cloudasset, not_cloudasset),
|
||||
(deleted, deleted_only),
|
||||
@@ -293,6 +295,7 @@ def query(
|
||||
no_description=no_description,
|
||||
no_likes=no_likes,
|
||||
no_location=no_location,
|
||||
no_keyword=no_keyword,
|
||||
no_place=no_place,
|
||||
no_title=no_title,
|
||||
not_burst=not_burst,
|
||||
|
||||
@@ -284,6 +284,7 @@ def _query_options_from_kwargs(**kwargs) -> QueryOptions:
|
||||
("incloud", "not_incloud"),
|
||||
("live", "not_live"),
|
||||
("location", "no_location"),
|
||||
("keyword", "no_keyword"),
|
||||
("missing", "not_missing"),
|
||||
("only_photos", "only_movies"),
|
||||
("panorama", "not_panorama"),
|
||||
@@ -301,6 +302,7 @@ def _query_options_from_kwargs(**kwargs) -> QueryOptions:
|
||||
all([any(kwargs["title"]), kwargs["no_title"]]),
|
||||
all([any(kwargs["description"]), kwargs["no_description"]]),
|
||||
all([any(kwargs["place"]), kwargs["no_place"]]),
|
||||
all([any(kwargs["keyword"]), kwargs["no_keyword"]]),
|
||||
]
|
||||
):
|
||||
raise IncompatibleQueryOptions
|
||||
|
||||
Binary file not shown.
@@ -2,13 +2,11 @@
|
||||
"""
|
||||
|
||||
import dataclasses
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import tempfile
|
||||
import typing as t
|
||||
from collections import namedtuple # pylint: disable=syntax-error
|
||||
from dataclasses import asdict, dataclass
|
||||
@@ -45,14 +43,13 @@ from .photokit import (
|
||||
from .phototemplate import RenderOptions
|
||||
from .rich_utils import add_rich_markup_tag
|
||||
from .uti import get_preferred_uti_extension
|
||||
from .utils import increment_filename, lineno, list_directory
|
||||
from .utils import hexdigest, increment_filename, lineno, list_directory
|
||||
|
||||
__all__ = [
|
||||
"ExportError",
|
||||
"ExportOptions",
|
||||
"ExportResults",
|
||||
"PhotoExporter",
|
||||
"hexdigest",
|
||||
"rename_jpeg_files",
|
||||
]
|
||||
|
||||
@@ -266,6 +263,7 @@ class ExportResults:
|
||||
exported_album=None,
|
||||
skipped_album=None,
|
||||
missing_album=None,
|
||||
metadata_changed=None,
|
||||
):
|
||||
self.exported = exported or []
|
||||
self.new = new or []
|
||||
@@ -292,6 +290,7 @@ class ExportResults:
|
||||
self.exported_album = exported_album or []
|
||||
self.skipped_album = skipped_album or []
|
||||
self.missing_album = missing_album or []
|
||||
self.metadata_changed = metadata_changed or []
|
||||
|
||||
def all_files(self):
|
||||
"""return all filenames contained in results"""
|
||||
@@ -342,6 +341,7 @@ class ExportResults:
|
||||
self.exported_album += other.exported_album
|
||||
self.skipped_album += other.skipped_album
|
||||
self.missing_album += other.missing_album
|
||||
self.metadata_changed += other.metadata_changed
|
||||
|
||||
return self
|
||||
|
||||
@@ -371,12 +371,14 @@ class ExportResults:
|
||||
+ f",exported_album={self.exported_album}"
|
||||
+ f",skipped_album={self.skipped_album}"
|
||||
+ f",missing_album={self.missing_album}"
|
||||
+ f",metadata_changed={self.metadata_changed}"
|
||||
+ ")"
|
||||
)
|
||||
|
||||
|
||||
class PhotoExporter:
|
||||
"""Export a photo"""
|
||||
|
||||
def __init__(self, photo: "PhotoInfo", tmpdir: t.Optional[str] = None):
|
||||
self.photo = photo
|
||||
self._render_options = RenderOptions()
|
||||
@@ -739,7 +741,7 @@ class PhotoExporter:
|
||||
return ShouldUpdate.EDITED_SIG_DIFFERENT
|
||||
|
||||
if options.force_update:
|
||||
current_digest = hexdigest(self.photo.json())
|
||||
current_digest = self.photo.hexdigest
|
||||
if current_digest != file_record.digest:
|
||||
# metadata in Photos changed, force update
|
||||
return ShouldUpdate.DIGEST_DIFFERENT
|
||||
@@ -1179,8 +1181,9 @@ class PhotoExporter:
|
||||
rec.dest_sig = fileutil.file_sig(dest)
|
||||
if options.exiftool:
|
||||
rec.exifdata = self._exiftool_json_sidecar(options)
|
||||
if options.force_update:
|
||||
rec.digest = hexdigest(photoinfo)
|
||||
if self.photo.hexdigest != rec.digest:
|
||||
results.metadata_changed = [dest_str]
|
||||
rec.digest = self.photo.hexdigest
|
||||
|
||||
return results
|
||||
|
||||
@@ -2011,13 +2014,6 @@ class PhotoExporter:
|
||||
f.close()
|
||||
|
||||
|
||||
def hexdigest(strval):
|
||||
"""hexdigest of a string, using blake2b"""
|
||||
h = hashlib.blake2b(digest_size=20)
|
||||
h.update(bytes(strval, "utf-8"))
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def _check_export_suffix(src, dest, edited):
|
||||
"""Helper function for exporting photos to check file extensions of destination path.
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import os
|
||||
import os.path
|
||||
import pathlib
|
||||
from datetime import timedelta, timezone
|
||||
from functools import cached_property
|
||||
from typing import Optional
|
||||
|
||||
import yaml
|
||||
@@ -54,7 +55,7 @@ from .scoreinfo import ScoreInfo
|
||||
from .searchinfo import SearchInfo
|
||||
from .text_detection import detect_text
|
||||
from .uti import get_preferred_uti_extension, get_uti_for_extension
|
||||
from .utils import _get_resource_loc, list_directory
|
||||
from .utils import _get_resource_loc, hexdigest, list_directory
|
||||
|
||||
__all__ = ["PhotoInfo", "PhotoInfoNone"]
|
||||
|
||||
@@ -892,38 +893,37 @@ class PhotoInfo:
|
||||
|
||||
return photopath
|
||||
|
||||
@property
|
||||
@cached_property
|
||||
def path_derivatives(self):
|
||||
"""Return any derivative (preview) images associated with the photo as a list of paths, sorted by file size (largest first)"""
|
||||
try:
|
||||
return self._path_derivatives
|
||||
except AttributeError:
|
||||
if self._db._db_version <= _PHOTOS_4_VERSION:
|
||||
self._path_derivatives = self._path_derivatives_4()
|
||||
return self._path_derivatives
|
||||
if self._db._db_version <= _PHOTOS_4_VERSION:
|
||||
return self._path_derivatives_4()
|
||||
|
||||
directory = self._uuid[0] # first char of uuid
|
||||
derivative_path = (
|
||||
pathlib.Path(self._db._library_path)
|
||||
/ "resources"
|
||||
/ "derivatives"
|
||||
/ directory
|
||||
)
|
||||
files = derivative_path.glob(f"{self.uuid}*.*")
|
||||
files = sorted(files, reverse=True, key=lambda f: f.stat().st_size)
|
||||
# return list of filename but skip .THM files (these are actually low-res thumbnails in JPEG format but with .THM extension)
|
||||
derivatives = [
|
||||
str(filename) for filename in files if filename.suffix != ".THM"
|
||||
]
|
||||
if (
|
||||
self.isphoto
|
||||
and len(derivatives) > 1
|
||||
and derivatives[0].endswith(".mov")
|
||||
):
|
||||
derivatives[1], derivatives[0] = derivatives[0], derivatives[1]
|
||||
if self.shared:
|
||||
return self._path_derivatives_5_shared()
|
||||
|
||||
self._path_derivatives = derivatives
|
||||
return self._path_derivatives
|
||||
directory = self._uuid[0] # first char of uuid
|
||||
derivative_path = (
|
||||
pathlib.Path(self._db._library_path) / f"resources/derivatives/{directory}"
|
||||
)
|
||||
files = list(derivative_path.glob(f"{self.uuid}*.*"))
|
||||
|
||||
# previews may be missing from derivatives path
|
||||
# there are what appear to be low res thumbnails in the "masters" subfolder
|
||||
thumb_path = (
|
||||
pathlib.Path(self._db._library_path)
|
||||
/ f"resources/derivatives/masters/{directory}/{self.uuid}_4_5005_c.jpeg"
|
||||
)
|
||||
if thumb_path.exists():
|
||||
files.append(thumb_path)
|
||||
|
||||
files = sorted(files, reverse=True, key=lambda f: f.stat().st_size)
|
||||
# return list of filename but skip .THM files (these are actually low-res thumbnails in JPEG format but with .THM extension)
|
||||
derivatives = [str(filename) for filename in files if filename.suffix != ".THM"]
|
||||
if self.isphoto and len(derivatives) > 1 and derivatives[0].endswith(".mov"):
|
||||
derivatives[1], derivatives[0] = derivatives[0], derivatives[1]
|
||||
|
||||
return derivatives
|
||||
|
||||
def _path_derivatives_4(self):
|
||||
"""Return paths to all derivative (preview) files for Photos <= 4"""
|
||||
@@ -933,10 +933,7 @@ class PhotoInfo:
|
||||
folder_id, file_id = _get_resource_loc(modelid)
|
||||
derivatives_root = (
|
||||
pathlib.Path(self._db._library_path)
|
||||
/ "resources"
|
||||
/ "proxies"
|
||||
/ "derivatives"
|
||||
/ folder_id
|
||||
/ f"resources/proxies/derivatives/{folder_id}"
|
||||
)
|
||||
|
||||
# photos appears to usually be in "00" subfolder but
|
||||
@@ -961,6 +958,19 @@ class PhotoInfo:
|
||||
# didn't find a derivatives path
|
||||
return []
|
||||
|
||||
def _path_derivatives_5_shared(self):
|
||||
"""Return paths to all derivative (preview) files for shared iCloud photos in Photos >= 5"""
|
||||
directory = self._uuid[0] # first char of uuid
|
||||
# only 1 derivative for shared photos and it's called 'UUID_4_5005_c.jpeg'
|
||||
derivative_path = (
|
||||
pathlib.Path(self._db._library_path)
|
||||
/ "resources/cloudsharing/resources/derivatives/masters"
|
||||
/ f"{directory}/{self.uuid}_4_5005_c.jpeg"
|
||||
)
|
||||
if derivative_path.exists():
|
||||
return [str(derivative_path)]
|
||||
return []
|
||||
|
||||
@property
|
||||
def panorama(self):
|
||||
"""Returns True if photo is a panorama, otherwise False"""
|
||||
@@ -1356,6 +1366,12 @@ class PhotoInfo:
|
||||
self._exiftool = exiftool
|
||||
return self._exiftool
|
||||
|
||||
@cached_property
|
||||
def hexdigest(self):
|
||||
"""Returns a unique digest of the photo's properties and metadata;
|
||||
useful for detecting changes in any property/metadata of the photo"""
|
||||
return hexdigest(self.json())
|
||||
|
||||
def detected_text(self, confidence_threshold=TEXT_DETECTION_CONFIDENCE_THRESHOLD):
|
||||
"""Detects text in photo and returns lists of results as (detected text, confidence)
|
||||
|
||||
|
||||
@@ -3076,6 +3076,8 @@ class PhotosDB:
|
||||
photos = _get_photos_by_attribute(
|
||||
photos, "keywords", keyword, options.ignore_case
|
||||
)
|
||||
elif options.no_keyword:
|
||||
photos = [p for p in photos if not p.keywords]
|
||||
|
||||
if person:
|
||||
photos = _get_photos_by_attribute(
|
||||
|
||||
@@ -56,6 +56,7 @@ class QueryOptions:
|
||||
no_description: search for photos with no description
|
||||
no_likes: search for shared photos with no likes
|
||||
no_location: search for photos with no location
|
||||
no_keyword: search for photos with no keywords
|
||||
no_place: search for photos with no place
|
||||
no_title: search for photos with no title
|
||||
not_burst: search for non-burst photos
|
||||
@@ -136,6 +137,7 @@ class QueryOptions:
|
||||
no_description: Optional[bool] = None
|
||||
no_likes: Optional[bool] = None
|
||||
no_location: Optional[bool] = None
|
||||
no_keyword: Optional[bool] = None
|
||||
no_place: Optional[bool] = None
|
||||
no_title: Optional[bool] = None
|
||||
not_burst: Optional[bool] = None
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import datetime
|
||||
import fnmatch
|
||||
import glob
|
||||
import hashlib
|
||||
import importlib
|
||||
import inspect
|
||||
import logging
|
||||
@@ -29,6 +30,7 @@ __all__ = [
|
||||
"expand_and_validate_filepath",
|
||||
"get_last_library_path",
|
||||
"get_system_library_path",
|
||||
"hexdigest",
|
||||
"increment_filename_with_count",
|
||||
"increment_filename",
|
||||
"lineno",
|
||||
@@ -514,6 +516,13 @@ def get_latest_version() -> Tuple[Optional[str], str]:
|
||||
return None, e
|
||||
|
||||
|
||||
def pluralize(count, singular, plural):
|
||||
def pluralize(count: Optional[int], singular: str, plural: str) -> str:
|
||||
"""Return singular or plural based on count"""
|
||||
return singular if count == 1 else plural
|
||||
|
||||
|
||||
def hexdigest(strval: str) -> str:
|
||||
"""hexdigest of a string, using blake2b"""
|
||||
h = hashlib.blake2b(digest_size=20)
|
||||
h.update(bytes(strval, "utf-8"))
|
||||
return h.hexdigest()
|
||||
|
||||
@@ -12,8 +12,12 @@ from osxphotos.exiftool import _ExifToolProc
|
||||
|
||||
from .test_catalina_10_15_7 import UUID_DICT_LOCAL
|
||||
|
||||
# run timewarp tests (configured with --timewarp)
|
||||
TEST_TIMEWARP = False
|
||||
|
||||
# don't clean up crash logs (configured with --no-cleanup)
|
||||
NO_CLEANUP = False
|
||||
|
||||
|
||||
def get_os_version():
|
||||
import platform
|
||||
@@ -68,6 +72,12 @@ def pytest_addoption(parser):
|
||||
parser.addoption(
|
||||
"--timewarp", action="store_true", default=False, help="run --timewarp tests"
|
||||
)
|
||||
parser.addoption(
|
||||
"--no-cleanup",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="don't clean up crash logs after tests",
|
||||
)
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
@@ -81,10 +91,15 @@ def pytest_configure(config):
|
||||
"markers", "timewarp: mark test as requiring --timewarp to run"
|
||||
)
|
||||
|
||||
# this is hacky but I can't figure out how to check config options in other fixtures
|
||||
if config.getoption("--timewarp"):
|
||||
global TEST_TIMEWARP
|
||||
TEST_TIMEWARP = True
|
||||
|
||||
if config.getoption("--no-cleanup"):
|
||||
global NO_CLEANUP
|
||||
NO_CLEANUP = True
|
||||
|
||||
|
||||
def pytest_collection_modifyitems(config, items):
|
||||
if not (config.getoption("--addalbum") and TEST_LIBRARY is not None):
|
||||
@@ -163,7 +178,7 @@ def delete_crash_logs():
|
||||
"""Delete left over crash logs from tests that were supposed to crash"""
|
||||
yield
|
||||
path = pathlib.Path(os.getcwd()) / "osxphotos_crash.log"
|
||||
if path.is_file():
|
||||
if path.is_file() and not NO_CLEANUP:
|
||||
path.unlink()
|
||||
|
||||
|
||||
|
||||
@@ -519,6 +519,7 @@ def test_path_derivatives(photosdb):
|
||||
derivs = [
|
||||
"D05A5FE3-15FB-49A1-A15D-AB3DA6F8B068_1_100_o.jpeg",
|
||||
"D05A5FE3-15FB-49A1-A15D-AB3DA6F8B068_1_105_c.jpeg",
|
||||
"D05A5FE3-15FB-49A1-A15D-AB3DA6F8B068_4_5005_c.jpeg",
|
||||
]
|
||||
for i, p in enumerate(path):
|
||||
assert p.endswith(derivs[i])
|
||||
|
||||
@@ -625,6 +625,7 @@ def test_path_derivatives(photosdb):
|
||||
derivs = [
|
||||
"D05A5FE3-15FB-49A1-A15D-AB3DA6F8B068_1_100_o.jpeg",
|
||||
"D05A5FE3-15FB-49A1-A15D-AB3DA6F8B068_1_105_c.jpeg",
|
||||
"D05A5FE3-15FB-49A1-A15D-AB3DA6F8B068_4_5005_c.jpeg",
|
||||
]
|
||||
for i, p in enumerate(path):
|
||||
assert p.endswith(derivs[i])
|
||||
|
||||
@@ -2711,6 +2711,27 @@ def test_query_keyword_4():
|
||||
assert len(json_got) == 6
|
||||
|
||||
|
||||
def test_query_no_keyword():
|
||||
"""Test query --no-keyword"""
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
result = runner.invoke(
|
||||
query,
|
||||
[
|
||||
"--json",
|
||||
"--db",
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
"--no-keyword",
|
||||
"--added-before",
|
||||
"2022-05-05",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
json_got = json.loads(result.output)
|
||||
assert len(json_got) == 11
|
||||
|
||||
|
||||
def test_query_person_1():
|
||||
"""Test query --person"""
|
||||
|
||||
@@ -7715,3 +7736,80 @@ def test_export_added_in_last():
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "Exporting" in result.output
|
||||
|
||||
|
||||
def test_export_limit():
|
||||
"""test export --limit"""
|
||||
|
||||
# Use --added-before so test doesn't break if photos added in the future
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
with runner.isolated_filesystem():
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
".",
|
||||
"--db",
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
"--update",
|
||||
"--limit",
|
||||
"20",
|
||||
"--added-before",
|
||||
"2022-05-07",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "limit: 20/20 exported" in result.output
|
||||
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
".",
|
||||
"--db",
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
"--update",
|
||||
"--limit",
|
||||
"20",
|
||||
"--added-before",
|
||||
"2022-05-07",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "limit: 5/20 exported" in result.output
|
||||
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
".",
|
||||
"--db",
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
"--update",
|
||||
"--limit",
|
||||
"20",
|
||||
"--added-before",
|
||||
"2022-05-07",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "limit: 0/20 exported" in result.output
|
||||
|
||||
def test_export_no_keyword():
|
||||
"""test export --no-keyword"""
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
with runner.isolated_filesystem():
|
||||
result = runner.invoke(
|
||||
export,
|
||||
[
|
||||
".",
|
||||
"--db",
|
||||
os.path.join(cwd, PHOTOS_DB_15_7),
|
||||
"--no-keyword",
|
||||
"--added-before",
|
||||
"2022-05-05",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "Exporting 11" in result.output
|
||||
33
tests/test_incloud_big_sur_10_16_0.py
Normal file
33
tests/test_incloud_big_sur_10_16_0.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# Test cloud photos
|
||||
|
||||
import pytest
|
||||
|
||||
import osxphotos
|
||||
|
||||
PHOTOS_DB_CLOUD = "tests/Test-Cloud-10.16.0.photoslibrary"
|
||||
|
||||
UUID_DICT = {
|
||||
"incloud": "FC638F58-84BE-4083-B5DE-F85BDC729062",
|
||||
"shared": "2094984A-21DC-4A6E-88A6-7344F648B92E",
|
||||
"cloudasset": "FC638F58-84BE-4083-B5DE-F85BDC729062",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def photosdb():
|
||||
return osxphotos.PhotosDB(dbfile=PHOTOS_DB_CLOUD)
|
||||
|
||||
|
||||
def test_incloud(photosdb):
|
||||
photos = photosdb.photos(uuid=[UUID_DICT["incloud"]])
|
||||
assert photos[0].incloud
|
||||
|
||||
|
||||
def test_cloudasset_1(photosdb):
|
||||
photos = photosdb.photos(uuid=[UUID_DICT["cloudasset"]])
|
||||
assert photos[0].iscloudasset
|
||||
|
||||
|
||||
def test_path_derivatives(photosdb):
|
||||
photo = photosdb.get_photo(UUID_DICT["shared"])
|
||||
assert photo.path_derivatives
|
||||
@@ -12,6 +12,7 @@ UUID_DICT = {
|
||||
"not_incloud": "33000A44-E4BA-43A3-9304-62A0195AB4D9",
|
||||
"cloudasset": "D11D25FF-5F31-47D2-ABA9-58418878DC15",
|
||||
"not_cloudasset": "6191423D-8DB8-4D4C-92BE-9BBBA308AAC4",
|
||||
"shared": "4AD7C8EF-2991-4519-9D3A-7F44A6F031BE",
|
||||
}
|
||||
|
||||
|
||||
@@ -52,3 +53,8 @@ def test_cloudasset_3():
|
||||
photos = photosdb.photos(uuid=[UUID_DICT["not_cloudasset"]])
|
||||
|
||||
assert not photos[0].iscloudasset
|
||||
|
||||
|
||||
def test_path_derivatives(photosdb):
|
||||
photo = photosdb.get_photo(UUID_DICT["shared"])
|
||||
assert photo.path_derivatives
|
||||
|
||||
@@ -524,6 +524,7 @@ def test_path_derivatives(photosdb):
|
||||
derivs = [
|
||||
"D05A5FE3-15FB-49A1-A15D-AB3DA6F8B068_1_100_o.jpeg",
|
||||
"D05A5FE3-15FB-49A1-A15D-AB3DA6F8B068_1_105_c.jpeg",
|
||||
"D05A5FE3-15FB-49A1-A15D-AB3DA6F8B068_4_5005_c.jpeg",
|
||||
]
|
||||
for i, p in enumerate(path):
|
||||
assert p.endswith(derivs[i])
|
||||
|
||||
@@ -579,6 +579,7 @@ def test_path_derivatives(photosdb):
|
||||
derivs = [
|
||||
"D05A5FE3-15FB-49A1-A15D-AB3DA6F8B068_1_100_o.jpeg",
|
||||
"D05A5FE3-15FB-49A1-A15D-AB3DA6F8B068_1_105_c.jpeg",
|
||||
"D05A5FE3-15FB-49A1-A15D-AB3DA6F8B068_4_5005_c.jpeg",
|
||||
]
|
||||
for i, p in enumerate(path):
|
||||
assert p.endswith(derivs[i])
|
||||
|
||||
Reference in New Issue
Block a user