Compare commits

..

14 Commits

Author SHA1 Message Date
Rhet Turnbull
35a4777ae4 Added --limit, #592 (#685) 2022-05-07 08:59:01 -07:00
Rhet Turnbull
9fddbefa66 Updated CHANGELOG.md [skip ci] 2022-05-06 21:33:08 -07:00
Rhet Turnbull
ff2e810d49 Version bump, updated docs 2022-05-06 21:26:27 -07:00
Rhet Turnbull
026e90a8ed Feature metadata changed 621 (#684)
* Added metadata_changed to ExportResults, #621

* Updated docs
2022-05-06 21:05:59 -07:00
Rhet Turnbull
95103f7c8d Updated CHANGELOG.md [skip ci] 2022-05-05 17:40:45 -07:00
Rhet Turnbull
57deb23988 Added --added-after, --added-before, --added-in-last, #439 2022-05-05 17:38:59 -07:00
Rhet Turnbull
4533057142 Added --added-after, --added-before, --added-in-last, #439 (#683) 2022-05-05 17:06:55 -07:00
Rhet Turnbull
3ed658a7d0 Updated to pytimeparse2, added tests for custom Click param types 2022-05-05 07:00:52 -07:00
Rhet Turnbull
fa991b8b48 Updated CHANGELOG.md [skip ci] 2022-05-03 22:28:29 -07:00
Rhet Turnbull
9bc5890589 Added moment_info, #71 2022-05-03 22:12:09 -07:00
Rhet Turnbull
e9bbfeca52 Fixed metavars to be consistent, #645 2022-05-03 06:34:19 -07:00
Rhet Turnbull
f42bee84c0 Added --force to timewarp to bypass confirmation 2022-05-02 08:06:48 -07:00
Rhet Turnbull
ac67ef2384 Added confirmation for timewarp, #677 2022-05-02 07:54:39 -07:00
Rhet Turnbull
1ae4ec4851 Updated CHANGELOG.md [skip ci] 2022-05-01 22:32:29 -07:00
58 changed files with 4608 additions and 2964 deletions

View File

@@ -1924,6 +1924,7 @@ cog.out(get_template_field_table())
|{exif.camera_make}|Camera make from original photo's EXIF information as imported by Photos, e.g. 'Apple'|
|{exif.camera_model}|Camera model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s'|
|{exif.lens_model}|Lens model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s back camera 4.15mm f/2.2'|
|{moment}|The moment title of the photo|
|{uuid}|Photo's internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'|
|{id}|A unique number for the photo based on its primary key in the Photos database. A sequential integer, e.g. 1, 2, 3...etc. Each asset associated with a photo (e.g. an image and Live Photo preview) will share the same id. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{id:05d}' which results in 00001, 00002, 00003...etc. |
|{album_seq}|An integer, starting at 0, indicating the photo's index (sequence) in the containing album. Only valid when used in a '--filename' template and only when '{album}' or '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{album_seq}_{original_name}"'. To start counting at a value other than 0, append append a period and the starting value to the field name. For example, to start counting at 1 instead of 0: '{album_seq.1}'. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{album_seq:05d}' which results in 00000, 00001, 00002...etc. This may result in incorrect sequences if you have duplicate albums with the same name; see also '{folder_album_seq}'.|
@@ -1942,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.1'|
|{osxphotos_version}|The osxphotos version, e.g. '0.48.4'|
|{osxphotos_cmd_line}|The full command line used to run osxphotos|
|{album}|Album(s) photo is contained in|
|{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder|

View File

@@ -4,6 +4,35 @@ 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.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
- Added moment_info, #71 [`9bc5890`](https://github.com/RhetTbull/osxphotos/commit/9bc5890589b7ff45d7b1e8bca4f958a6b4dc5fad)
- Added --force to timewarp to bypass confirmation [`f42bee8`](https://github.com/RhetTbull/osxphotos/commit/f42bee84c08cf8c6883058a8c2d45dfe9c3e2357)
- Added confirmation for timewarp, #677 [`ac67ef2`](https://github.com/RhetTbull/osxphotos/commit/ac67ef23846fb2a35211be8b63f5201a5567c68e)
#### [v0.48.1](https://github.com/RhetTbull/osxphotos/compare/v0.48.0...v0.48.1)
> 1 May 2022
- Feature timewarp function [`#678`](https://github.com/RhetTbull/osxphotos/pull/678)
- Updated docs [`6070616`](https://github.com/RhetTbull/osxphotos/commit/60706167173f719d70e21193acef89f6252767e6)
#### [v0.48.0](https://github.com/RhetTbull/osxphotos/compare/v0.47.13...v0.48.0)
> 1 May 2022

933
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -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: bea67f756056dcbf51004e51b5dc2067
config: 8e75e979ef179f86aec0b772d60e05d7
tags: 645f666f9bcd5a90fca523b33c5a78b7

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.48.1 documentation</title>
<title>Overview: module code - osxphotos 0.48.4 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.4 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.4 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

@@ -1,54 +1,217 @@
<!doctype html>
<html class="no-js">
<head><meta charset="utf-8"/>
<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" />
<!DOCTYPE html>
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
<title>osxphotos._constants - osxphotos 0.48.1 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" />
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>osxphotos._constants &#8212; osxphotos 0.47.9 documentation</title>
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../../_static/alabaster.css" />
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
<script src="../../_static/jquery.js"></script>
<script src="../../_static/underscore.js"></script>
<script src="../../_static/doctools.js"></script>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
<link rel="stylesheet" href="../../_static/custom.css" type="text/css" />
<style>
body {
--color-code-background: #f8f8f8;
--color-code-foreground: black;
}
@media not print {
body[data-theme="dark"] {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
}
@media (prefers-color-scheme: dark) {
body:not([data-theme="light"]) {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
}
}
}
</style></head>
<body>
<script>
document.body.dataset.theme = localStorage.getItem("theme") || "auto";
</script>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-toc" viewBox="0 0 24 24">
<title>Contents</title>
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 1024 1024">
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM115.4 518.9L271.7 642c5.8 4.6 14.4.5 14.4-6.9V388.9c0-7.4-8.5-11.5-14.4-6.9L115.4 505.1a8.74 8.74 0 0 0 0 13.8z"/>
</svg>
</symbol>
<symbol id="svg-menu" viewBox="0 0 24 24">
<title>Menu</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-menu">
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</symbol>
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
<title>Expand</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-chevron-right">
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24">
<title>Light mode</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather-sun">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24">
<title>Dark mode</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-moon">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" />
</svg>
</symbol>
<symbol id="svg-sun-half" viewBox="0 0 24 24">
<title>Auto light/dark mode</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-shadow">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="12" cy="12" r="9" />
<path d="M13 12h5" />
<path d="M13 15h4" />
<path d="M13 18h1" />
<path d="M13 9h4" />
<path d="M13 6h1" />
</svg>
</symbol>
</svg>
<input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation">
<input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc">
<label class="overlay sidebar-overlay" for="__navigation">
<div class="visually-hidden">Hide navigation sidebar</div>
</label>
<label class="overlay toc-overlay" for="__toc">
<div class="visually-hidden">Hide table of contents sidebar</div>
</label>
<div class="page">
<header class="mobile-header">
<div class="header-left">
<label class="nav-overlay-icon" for="__navigation">
<div class="visually-hidden">Toggle site navigation sidebar</div>
<i class="icon"><svg><use href="#svg-menu"></use></svg></i>
</label>
</div>
<div class="header-center">
<a href="../../index.html"><div class="brand">osxphotos 0.48.1 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
<button class="theme-toggle">
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
</button>
</div>
<label class="toc-overlay-icon toc-header-icon no-toc" for="__toc">
<div class="visually-hidden">Toggle table of contents sidebar</div>
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
</label>
</div>
</header>
<aside class="sidebar-drawer">
<div class="sidebar-container">
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
</head><body>
<span class="sidebar-brand-text">osxphotos 0.48.1 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">
<input type="hidden" name="check_keywords" value="yes">
<input type="hidden" name="area" value="default">
</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="../../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 class="document">
<div class="documentwrapper">
<div class="bodywrapper">
</div>
</div>
<div class="body" role="main">
<h1>Source code for osxphotos._constants</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot;</span>
</div>
</div>
</aside>
<div class="main">
<div class="content">
<div class="article-container">
<a href="#" class="back-to-top muted-link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z"></path>
</svg>
<span>Back to top</span>
</a>
<div class="content-icon-container"><div class="theme-toggle-container theme-toggle-content">
<button class="theme-toggle">
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
</button>
</div>
<label class="toc-overlay-icon toc-content-icon no-toc" for="__toc">
<div class="visually-hidden">Toggle table of contents sidebar</div>
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
</label>
</div>
<article role="main">
<h1>Source code for osxphotos._constants</h1><div class="highlight"><pre>
<span></span><span class="sd">"""</span>
<span class="sd">Constants used by osxphotos </span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">"""</span>
<span class="kn">import</span> <span class="nn">os.path</span>
<span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span>
<span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">Enum</span>
<span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">&quot;osxphotos&quot;</span>
<span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">"osxphotos"</span>
<span class="n">OSXPHOTOS_URL</span> <span class="o">=</span> <span class="s2">&quot;https://github.com/RhetTbull/osxphotos&quot;</span>
<span class="n">OSXPHOTOS_URL</span> <span class="o">=</span> <span class="s2">"https://github.com/RhetTbull/osxphotos"</span>
<span class="c1"># Time delta: add this to Photos times to get unix time</span>
<span class="c1"># Apple Epoch is Jan 1, 2001</span>
<span class="n">TIME_DELTA</span> <span class="o">=</span> <span class="p">(</span><span class="n">datetime</span><span class="p">(</span><span class="mi">2001</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-</span> <span class="n">datetime</span><span class="p">(</span><span class="mi">1970</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span><span class="o">.</span><span class="n">total_seconds</span><span class="p">()</span>
<span class="c1"># Unicode format to use for comparing strings</span>
<span class="n">UNICODE_FORMAT</span> <span class="o">=</span> <span class="s2">&quot;NFC&quot;</span>
<span class="n">UNICODE_FORMAT</span> <span class="o">=</span> <span class="s2">"NFC"</span>
<span class="c1"># which Photos library database versions have been tested</span>
<span class="c1"># Photos 2.0 (10.12.6) == 2622</span>
@@ -56,23 +219,23 @@
<span class="c1"># Photos 4.0 (10.14.5) == 4016</span>
<span class="c1"># Photos 4.0 (10.14.6) == 4025</span>
<span class="c1"># Photos 5.0 (10.15.0) == 6000 or 5001</span>
<span class="n">_TESTED_DB_VERSIONS</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;6000&quot;</span><span class="p">,</span> <span class="s2">&quot;5001&quot;</span><span class="p">,</span> <span class="s2">&quot;4025&quot;</span><span class="p">,</span> <span class="s2">&quot;4016&quot;</span><span class="p">,</span> <span class="s2">&quot;3301&quot;</span><span class="p">,</span> <span class="s2">&quot;2622&quot;</span><span class="p">]</span>
<span class="n">_TESTED_DB_VERSIONS</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"6000"</span><span class="p">,</span> <span class="s2">"5001"</span><span class="p">,</span> <span class="s2">"4025"</span><span class="p">,</span> <span class="s2">"4016"</span><span class="p">,</span> <span class="s2">"3301"</span><span class="p">,</span> <span class="s2">"2622"</span><span class="p">]</span>
<span class="c1"># database model versions (applies to Photos 5, Photos 6)</span>
<span class="c1"># these come from PLModelVersion key in binary plist in Z_METADATA.Z_PLIST</span>
<span class="c1"># Photos 5 (10.15.1) == 13537</span>
<span class="c1"># Photos 5 (10.15.4, 10.15.5, 10.15.6) == 13703</span>
<span class="c1"># Photos 6 (10.16.0 Beta) == 14104</span>
<span class="n">_TEST_MODEL_VERSIONS</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;13537&quot;</span><span class="p">,</span> <span class="s2">&quot;13703&quot;</span><span class="p">,</span> <span class="s2">&quot;14104&quot;</span><span class="p">]</span>
<span class="n">_TEST_MODEL_VERSIONS</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"13537"</span><span class="p">,</span> <span class="s2">"13703"</span><span class="p">,</span> <span class="s2">"14104"</span><span class="p">]</span>
<span class="n">_PHOTOS_2_VERSION</span> <span class="o">=</span> <span class="s2">&quot;2622&quot;</span>
<span class="n">_PHOTOS_2_VERSION</span> <span class="o">=</span> <span class="s2">"2622"</span>
<span class="c1"># only version 3 - 4 have RKVersion.selfPortrait</span>
<span class="n">_PHOTOS_3_VERSION</span> <span class="o">=</span> <span class="s2">&quot;3301&quot;</span>
<span class="n">_PHOTOS_3_VERSION</span> <span class="o">=</span> <span class="s2">"3301"</span>
<span class="c1"># versions 5.0 and later have a different database structure</span>
<span class="n">_PHOTOS_4_VERSION</span> <span class="o">=</span> <span class="s2">&quot;4025&quot;</span> <span class="c1"># latest Mojove version on 10.14.6</span>
<span class="n">_PHOTOS_5_VERSION</span> <span class="o">=</span> <span class="s2">&quot;5000&quot;</span> <span class="c1"># I&#39;ve seen both 5001 and 6000. 6000 is most common on Catalina and up but there are some version 5001 database in the wild</span>
<span class="n">_PHOTOS_4_VERSION</span> <span class="o">=</span> <span class="s2">"4025"</span> <span class="c1"># latest Mojove version on 10.14.6</span>
<span class="n">_PHOTOS_5_VERSION</span> <span class="o">=</span> <span class="s2">"5000"</span> <span class="c1"># I've seen both 5001 and 6000. 6000 is most common on Catalina and up but there are some version 5001 database in the wild</span>
<span class="c1"># Ranges for model version by Photos version</span>
<span class="n">_PHOTOS_5_MODEL_VERSION</span> <span class="o">=</span> <span class="p">[</span><span class="mi">13000</span><span class="p">,</span> <span class="mi">13999</span><span class="p">]</span>
@@ -85,82 +248,82 @@
<span class="c1"># some table names differ between Photos 5 and Photos 6</span>
<span class="n">_DB_TABLE_NAMES</span> <span class="o">=</span> <span class="p">{</span>
<span class="mi">5</span><span class="p">:</span> <span class="p">{</span>
<span class="s2">&quot;ASSET&quot;</span><span class="p">:</span> <span class="s2">&quot;ZGENERICASSET&quot;</span><span class="p">,</span>
<span class="s2">&quot;KEYWORD_JOIN&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_1KEYWORDS.Z_37KEYWORDS&quot;</span><span class="p">,</span>
<span class="s2">&quot;ALBUM_JOIN&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_26ASSETS.Z_34ASSETS&quot;</span><span class="p">,</span>
<span class="s2">&quot;ALBUM_SORT_ORDER&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_26ASSETS.Z_FOK_34ASSETS&quot;</span><span class="p">,</span>
<span class="s2">&quot;IMPORT_FOK&quot;</span><span class="p">:</span> <span class="s2">&quot;ZGENERICASSET.Z_FOK_IMPORTSESSION&quot;</span><span class="p">,</span>
<span class="s2">&quot;DEPTH_STATE&quot;</span><span class="p">:</span> <span class="s2">&quot;ZGENERICASSET.ZDEPTHSTATES&quot;</span><span class="p">,</span>
<span class="s2">&quot;UTI_ORIGINAL&quot;</span><span class="p">:</span> <span class="s2">&quot;ZINTERNALRESOURCE.ZUNIFORMTYPEIDENTIFIER&quot;</span><span class="p">,</span>
<span class="s2">&quot;ASSET_ALBUM_JOIN&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_26ASSETS.Z_26ALBUMS&quot;</span><span class="p">,</span>
<span class="s2">&quot;ASSET_ALBUM_TABLE&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_26ASSETS&quot;</span><span class="p">,</span>
<span class="s2">&quot;HDR_TYPE&quot;</span><span class="p">:</span> <span class="s2">&quot;ZCUSTOMRENDEREDVALUE&quot;</span><span class="p">,</span>
<span class="s2">"ASSET"</span><span class="p">:</span> <span class="s2">"ZGENERICASSET"</span><span class="p">,</span>
<span class="s2">"KEYWORD_JOIN"</span><span class="p">:</span> <span class="s2">"Z_1KEYWORDS.Z_37KEYWORDS"</span><span class="p">,</span>
<span class="s2">"ALBUM_JOIN"</span><span class="p">:</span> <span class="s2">"Z_26ASSETS.Z_34ASSETS"</span><span class="p">,</span>
<span class="s2">"ALBUM_SORT_ORDER"</span><span class="p">:</span> <span class="s2">"Z_26ASSETS.Z_FOK_34ASSETS"</span><span class="p">,</span>
<span class="s2">"IMPORT_FOK"</span><span class="p">:</span> <span class="s2">"ZGENERICASSET.Z_FOK_IMPORTSESSION"</span><span class="p">,</span>
<span class="s2">"DEPTH_STATE"</span><span class="p">:</span> <span class="s2">"ZGENERICASSET.ZDEPTHSTATES"</span><span class="p">,</span>
<span class="s2">"UTI_ORIGINAL"</span><span class="p">:</span> <span class="s2">"ZINTERNALRESOURCE.ZUNIFORMTYPEIDENTIFIER"</span><span class="p">,</span>
<span class="s2">"ASSET_ALBUM_JOIN"</span><span class="p">:</span> <span class="s2">"Z_26ASSETS.Z_26ALBUMS"</span><span class="p">,</span>
<span class="s2">"ASSET_ALBUM_TABLE"</span><span class="p">:</span> <span class="s2">"Z_26ASSETS"</span><span class="p">,</span>
<span class="s2">"HDR_TYPE"</span><span class="p">:</span> <span class="s2">"ZCUSTOMRENDEREDVALUE"</span><span class="p">,</span>
<span class="p">},</span>
<span class="mi">6</span><span class="p">:</span> <span class="p">{</span>
<span class="s2">&quot;ASSET&quot;</span><span class="p">:</span> <span class="s2">&quot;ZASSET&quot;</span><span class="p">,</span>
<span class="s2">&quot;KEYWORD_JOIN&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_1KEYWORDS.Z_36KEYWORDS&quot;</span><span class="p">,</span>
<span class="s2">&quot;ALBUM_JOIN&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_26ASSETS.Z_3ASSETS&quot;</span><span class="p">,</span>
<span class="s2">&quot;ALBUM_SORT_ORDER&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_26ASSETS.Z_FOK_3ASSETS&quot;</span><span class="p">,</span>
<span class="s2">&quot;IMPORT_FOK&quot;</span><span class="p">:</span> <span class="s2">&quot;null&quot;</span><span class="p">,</span>
<span class="s2">&quot;DEPTH_STATE&quot;</span><span class="p">:</span> <span class="s2">&quot;ZASSET.ZDEPTHTYPE&quot;</span><span class="p">,</span>
<span class="s2">&quot;UTI_ORIGINAL&quot;</span><span class="p">:</span> <span class="s2">&quot;ZINTERNALRESOURCE.ZUNIFORMTYPEIDENTIFIER&quot;</span><span class="p">,</span>
<span class="s2">&quot;ASSET_ALBUM_JOIN&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_26ASSETS.Z_26ALBUMS&quot;</span><span class="p">,</span>
<span class="s2">&quot;ASSET_ALBUM_TABLE&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_26ASSETS&quot;</span><span class="p">,</span>
<span class="s2">&quot;HDR_TYPE&quot;</span><span class="p">:</span> <span class="s2">&quot;ZCUSTOMRENDEREDVALUE&quot;</span><span class="p">,</span>
<span class="s2">"ASSET"</span><span class="p">:</span> <span class="s2">"ZASSET"</span><span class="p">,</span>
<span class="s2">"KEYWORD_JOIN"</span><span class="p">:</span> <span class="s2">"Z_1KEYWORDS.Z_36KEYWORDS"</span><span class="p">,</span>
<span class="s2">"ALBUM_JOIN"</span><span class="p">:</span> <span class="s2">"Z_26ASSETS.Z_3ASSETS"</span><span class="p">,</span>
<span class="s2">"ALBUM_SORT_ORDER"</span><span class="p">:</span> <span class="s2">"Z_26ASSETS.Z_FOK_3ASSETS"</span><span class="p">,</span>
<span class="s2">"IMPORT_FOK"</span><span class="p">:</span> <span class="s2">"null"</span><span class="p">,</span>
<span class="s2">"DEPTH_STATE"</span><span class="p">:</span> <span class="s2">"ZASSET.ZDEPTHTYPE"</span><span class="p">,</span>
<span class="s2">"UTI_ORIGINAL"</span><span class="p">:</span> <span class="s2">"ZINTERNALRESOURCE.ZUNIFORMTYPEIDENTIFIER"</span><span class="p">,</span>
<span class="s2">"ASSET_ALBUM_JOIN"</span><span class="p">:</span> <span class="s2">"Z_26ASSETS.Z_26ALBUMS"</span><span class="p">,</span>
<span class="s2">"ASSET_ALBUM_TABLE"</span><span class="p">:</span> <span class="s2">"Z_26ASSETS"</span><span class="p">,</span>
<span class="s2">"HDR_TYPE"</span><span class="p">:</span> <span class="s2">"ZCUSTOMRENDEREDVALUE"</span><span class="p">,</span>
<span class="p">},</span>
<span class="mi">7</span><span class="p">:</span> <span class="p">{</span>
<span class="s2">&quot;ASSET&quot;</span><span class="p">:</span> <span class="s2">&quot;ZASSET&quot;</span><span class="p">,</span>
<span class="s2">&quot;KEYWORD_JOIN&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_1KEYWORDS.Z_38KEYWORDS&quot;</span><span class="p">,</span>
<span class="s2">&quot;ALBUM_JOIN&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_27ASSETS.Z_3ASSETS&quot;</span><span class="p">,</span>
<span class="s2">&quot;ALBUM_SORT_ORDER&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_27ASSETS.Z_FOK_3ASSETS&quot;</span><span class="p">,</span>
<span class="s2">&quot;IMPORT_FOK&quot;</span><span class="p">:</span> <span class="s2">&quot;null&quot;</span><span class="p">,</span>
<span class="s2">&quot;DEPTH_STATE&quot;</span><span class="p">:</span> <span class="s2">&quot;ZASSET.ZDEPTHTYPE&quot;</span><span class="p">,</span>
<span class="s2">&quot;UTI_ORIGINAL&quot;</span><span class="p">:</span> <span class="s2">&quot;ZINTERNALRESOURCE.ZCOMPACTUTI&quot;</span><span class="p">,</span>
<span class="s2">&quot;ASSET_ALBUM_JOIN&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_27ASSETS.Z_27ALBUMS&quot;</span><span class="p">,</span>
<span class="s2">&quot;ASSET_ALBUM_TABLE&quot;</span><span class="p">:</span> <span class="s2">&quot;Z_27ASSETS&quot;</span><span class="p">,</span>
<span class="s2">&quot;HDR_TYPE&quot;</span><span class="p">:</span> <span class="s2">&quot;ZHDRTYPE&quot;</span><span class="p">,</span>
<span class="s2">"ASSET"</span><span class="p">:</span> <span class="s2">"ZASSET"</span><span class="p">,</span>
<span class="s2">"KEYWORD_JOIN"</span><span class="p">:</span> <span class="s2">"Z_1KEYWORDS.Z_38KEYWORDS"</span><span class="p">,</span>
<span class="s2">"ALBUM_JOIN"</span><span class="p">:</span> <span class="s2">"Z_27ASSETS.Z_3ASSETS"</span><span class="p">,</span>
<span class="s2">"ALBUM_SORT_ORDER"</span><span class="p">:</span> <span class="s2">"Z_27ASSETS.Z_FOK_3ASSETS"</span><span class="p">,</span>
<span class="s2">"IMPORT_FOK"</span><span class="p">:</span> <span class="s2">"null"</span><span class="p">,</span>
<span class="s2">"DEPTH_STATE"</span><span class="p">:</span> <span class="s2">"ZASSET.ZDEPTHTYPE"</span><span class="p">,</span>
<span class="s2">"UTI_ORIGINAL"</span><span class="p">:</span> <span class="s2">"ZINTERNALRESOURCE.ZCOMPACTUTI"</span><span class="p">,</span>
<span class="s2">"ASSET_ALBUM_JOIN"</span><span class="p">:</span> <span class="s2">"Z_27ASSETS.Z_27ALBUMS"</span><span class="p">,</span>
<span class="s2">"ASSET_ALBUM_TABLE"</span><span class="p">:</span> <span class="s2">"Z_27ASSETS"</span><span class="p">,</span>
<span class="s2">"HDR_TYPE"</span><span class="p">:</span> <span class="s2">"ZHDRTYPE"</span><span class="p">,</span>
<span class="p">},</span>
<span class="p">}</span>
<span class="c1"># which version operating systems have been tested</span>
<span class="n">_TESTED_OS_VERSIONS</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">(</span><span class="s2">&quot;10&quot;</span><span class="p">,</span> <span class="s2">&quot;12&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;10&quot;</span><span class="p">,</span> <span class="s2">&quot;13&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;10&quot;</span><span class="p">,</span> <span class="s2">&quot;14&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;10&quot;</span><span class="p">,</span> <span class="s2">&quot;15&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;10&quot;</span><span class="p">,</span> <span class="s2">&quot;16&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;11&quot;</span><span class="p">,</span> <span class="s2">&quot;0&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;11&quot;</span><span class="p">,</span> <span class="s2">&quot;1&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;11&quot;</span><span class="p">,</span> <span class="s2">&quot;2&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;11&quot;</span><span class="p">,</span> <span class="s2">&quot;3&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;11&quot;</span><span class="p">,</span> <span class="s2">&quot;4&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;11&quot;</span><span class="p">,</span> <span class="s2">&quot;5&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;11&quot;</span><span class="p">,</span> <span class="s2">&quot;6&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;12&quot;</span><span class="p">,</span> <span class="s2">&quot;0&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;12&quot;</span><span class="p">,</span> <span class="s2">&quot;1&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;12&quot;</span><span class="p">,</span> <span class="s2">&quot;2&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">&quot;12&quot;</span><span class="p">,</span> <span class="s2">&quot;3&quot;</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"10"</span><span class="p">,</span> <span class="s2">"12"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"10"</span><span class="p">,</span> <span class="s2">"13"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"10"</span><span class="p">,</span> <span class="s2">"14"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"10"</span><span class="p">,</span> <span class="s2">"15"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"10"</span><span class="p">,</span> <span class="s2">"16"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"11"</span><span class="p">,</span> <span class="s2">"0"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"11"</span><span class="p">,</span> <span class="s2">"1"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"11"</span><span class="p">,</span> <span class="s2">"2"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"11"</span><span class="p">,</span> <span class="s2">"3"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"11"</span><span class="p">,</span> <span class="s2">"4"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"11"</span><span class="p">,</span> <span class="s2">"5"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"11"</span><span class="p">,</span> <span class="s2">"6"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"12"</span><span class="p">,</span> <span class="s2">"0"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"12"</span><span class="p">,</span> <span class="s2">"1"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"12"</span><span class="p">,</span> <span class="s2">"2"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"12"</span><span class="p">,</span> <span class="s2">"3"</span><span class="p">),</span>
<span class="p">]</span>
<span class="c1"># Photos 5 has persons who are empty string if unidentified face</span>
<span class="n">_UNKNOWN_PERSON</span> <span class="o">=</span> <span class="s2">&quot;_UNKNOWN_&quot;</span>
<span class="n">_UNKNOWN_PERSON</span> <span class="o">=</span> <span class="s2">"_UNKNOWN_"</span>
<span class="c1"># photos with no reverse geolocation info (place)</span>
<span class="n">_UNKNOWN_PLACE</span> <span class="o">=</span> <span class="s2">&quot;_UNKNOWN_&quot;</span>
<span class="n">_UNKNOWN_PLACE</span> <span class="o">=</span> <span class="s2">"_UNKNOWN_"</span>
<span class="n">_EXIF_TOOL_URL</span> <span class="o">=</span> <span class="s2">&quot;https://exiftool.org/&quot;</span>
<span class="n">_EXIF_TOOL_URL</span> <span class="o">=</span> <span class="s2">"https://exiftool.org/"</span>
<span class="c1"># Where are shared iCloud photos located?</span>
<span class="n">_PHOTOS_5_SHARED_PHOTO_PATH</span> <span class="o">=</span> <span class="s2">&quot;resources/cloudsharing/data&quot;</span>
<span class="n">_PHOTOS_5_SHARED_PHOTO_PATH</span> <span class="o">=</span> <span class="s2">"resources/cloudsharing/data"</span>
<span class="c1"># What type of file? Based on ZGENERICASSET.ZKIND in Photos 5 database</span>
<span class="n">_PHOTO_TYPE</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">_MOVIE_TYPE</span> <span class="o">=</span> <span class="mi">1</span>
<span class="c1"># Name of XMP template file</span>
<span class="n">_TEMPLATE_DIR</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="vm">__file__</span><span class="p">),</span> <span class="s2">&quot;templates&quot;</span><span class="p">)</span>
<span class="n">_XMP_TEMPLATE_NAME</span> <span class="o">=</span> <span class="s2">&quot;xmp_sidecar.mako&quot;</span>
<span class="n">_XMP_TEMPLATE_NAME_BETA</span> <span class="o">=</span> <span class="s2">&quot;xmp_sidecar_beta.mako&quot;</span>
<span class="n">_TEMPLATE_DIR</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="vm">__file__</span><span class="p">),</span> <span class="s2">"templates"</span><span class="p">)</span>
<span class="n">_XMP_TEMPLATE_NAME</span> <span class="o">=</span> <span class="s2">"xmp_sidecar.mako"</span>
<span class="n">_XMP_TEMPLATE_NAME_BETA</span> <span class="o">=</span> <span class="s2">"xmp_sidecar_beta.mako"</span>
<span class="c1"># Constants used for processing folders and albums</span>
<span class="n">_PHOTOS_5_ALBUM_KIND</span> <span class="o">=</span> <span class="mi">2</span> <span class="c1"># normal user album</span>
@@ -175,20 +338,20 @@
<span class="n">_PHOTOS_4_ALBUM_TYPE_PROJECT</span> <span class="o">=</span> <span class="mi">9</span> <span class="c1"># RKAlbum.albumType</span>
<span class="n">_PHOTOS_4_ALBUM_TYPE_SLIDESHOW</span> <span class="o">=</span> <span class="mi">8</span> <span class="c1"># RKAlbum.albumType</span>
<span class="n">_PHOTOS_4_TOP_LEVEL_ALBUMS</span> <span class="o">=</span> <span class="p">[</span>
<span class="s2">&quot;TopLevelAlbums&quot;</span><span class="p">,</span>
<span class="s2">&quot;TopLevelKeepsakes&quot;</span><span class="p">,</span>
<span class="s2">&quot;TopLevelSlideshows&quot;</span><span class="p">,</span>
<span class="s2">"TopLevelAlbums"</span><span class="p">,</span>
<span class="s2">"TopLevelKeepsakes"</span><span class="p">,</span>
<span class="s2">"TopLevelSlideshows"</span><span class="p">,</span>
<span class="p">]</span>
<span class="n">_PHOTOS_4_ROOT_FOLDER</span> <span class="o">=</span> <span class="s2">&quot;LibraryFolder&quot;</span>
<span class="n">_PHOTOS_4_ROOT_FOLDER</span> <span class="o">=</span> <span class="s2">"LibraryFolder"</span>
<span class="c1"># EXIF related constants</span>
<span class="c1"># max keyword length for IPTC:Keyword, reference</span>
<span class="c1"># https://www.iptc.org/std/photometadata/documentation/userguide/</span>
<span class="n">_MAX_IPTC_KEYWORD_LEN</span> <span class="o">=</span> <span class="mi">64</span>
<span class="c1"># Sentinel value for detecting if a template in keyword_template doesn&#39;t match</span>
<span class="c1"># Sentinel value for detecting if a template in keyword_template doesn't match</span>
<span class="c1"># If anyone has a keyword matching this, then too bad...</span>
<span class="n">_OSXPHOTOS_NONE_SENTINEL</span> <span class="o">=</span> <span class="s2">&quot;OSXPhotosXYZZY42_Sentinel$&quot;</span>
<span class="n">_OSXPHOTOS_NONE_SENTINEL</span> <span class="o">=</span> <span class="s2">"OSXPhotosXYZZY42_Sentinel$"</span>
<span class="c1"># SearchInfo categories for Photos 5, corresponds to categories in database/search/psi.sqlite</span>
<span class="n">SEARCH_CATEGORY_LABEL</span> <span class="o">=</span> <span class="mi">2024</span>
@@ -260,13 +423,13 @@
<span class="n">DEFAULT_JPEG_QUALITY</span> <span class="o">=</span> <span class="mf">1.0</span>
<span class="c1"># Default suffix to add to edited images</span>
<span class="n">DEFAULT_EDITED_SUFFIX</span> <span class="o">=</span> <span class="s2">&quot;_edited&quot;</span>
<span class="n">DEFAULT_EDITED_SUFFIX</span> <span class="o">=</span> <span class="s2">"_edited"</span>
<span class="c1"># Default suffix to add to original images</span>
<span class="n">DEFAULT_ORIGINAL_SUFFIX</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
<span class="n">DEFAULT_ORIGINAL_SUFFIX</span> <span class="o">=</span> <span class="s2">""</span>
<span class="c1"># Default suffix to add to preview images</span>
<span class="n">DEFAULT_PREVIEW_SUFFIX</span> <span class="o">=</span> <span class="s2">&quot;_preview&quot;</span>
<span class="n">DEFAULT_PREVIEW_SUFFIX</span> <span class="o">=</span> <span class="s2">"_preview"</span>
<span class="c1"># Bit masks for --sidecar</span>
<span class="n">SIDECAR_JSON</span> <span class="o">=</span> <span class="mh">0x1</span>
@@ -275,28 +438,28 @@
<span class="c1"># supported attributes for --xattr-template</span>
<span class="n">EXTENDED_ATTRIBUTE_NAMES</span> <span class="o">=</span> <span class="p">[</span>
<span class="s2">&quot;authors&quot;</span><span class="p">,</span>
<span class="s2">&quot;comment&quot;</span><span class="p">,</span>
<span class="s2">&quot;copyright&quot;</span><span class="p">,</span>
<span class="s2">&quot;creator&quot;</span><span class="p">,</span>
<span class="s2">&quot;description&quot;</span><span class="p">,</span>
<span class="s2">&quot;findercomment&quot;</span><span class="p">,</span>
<span class="s2">&quot;headline&quot;</span><span class="p">,</span>
<span class="s2">&quot;keywords&quot;</span><span class="p">,</span>
<span class="s2">&quot;participants&quot;</span><span class="p">,</span>
<span class="s2">&quot;projects&quot;</span><span class="p">,</span>
<span class="s2">&quot;rating&quot;</span><span class="p">,</span>
<span class="s2">&quot;subject&quot;</span><span class="p">,</span>
<span class="s2">&quot;title&quot;</span><span class="p">,</span>
<span class="s2">&quot;version&quot;</span><span class="p">,</span>
<span class="s2">"authors"</span><span class="p">,</span>
<span class="s2">"comment"</span><span class="p">,</span>
<span class="s2">"copyright"</span><span class="p">,</span>
<span class="s2">"creator"</span><span class="p">,</span>
<span class="s2">"description"</span><span class="p">,</span>
<span class="s2">"findercomment"</span><span class="p">,</span>
<span class="s2">"headline"</span><span class="p">,</span>
<span class="s2">"keywords"</span><span class="p">,</span>
<span class="s2">"participants"</span><span class="p">,</span>
<span class="s2">"projects"</span><span class="p">,</span>
<span class="s2">"rating"</span><span class="p">,</span>
<span class="s2">"subject"</span><span class="p">,</span>
<span class="s2">"title"</span><span class="p">,</span>
<span class="s2">"version"</span><span class="p">,</span>
<span class="p">]</span>
<span class="n">EXTENDED_ATTRIBUTE_NAMES_QUOTED</span> <span class="o">=</span> <span class="p">[</span><span class="sa">f</span><span class="s2">&quot;&#39;</span><span class="si">{</span><span class="n">x</span><span class="si">}</span><span class="s2">&#39;&quot;</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">EXTENDED_ATTRIBUTE_NAMES</span><span class="p">]</span>
<span class="n">EXTENDED_ATTRIBUTE_NAMES_QUOTED</span> <span class="o">=</span> <span class="p">[</span><span class="sa">f</span><span class="s2">"'</span><span class="si">{</span><span class="n">x</span><span class="si">}</span><span class="s2">'"</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">EXTENDED_ATTRIBUTE_NAMES</span><span class="p">]</span>
<span class="c1"># name of export DB</span>
<span class="n">OSXPHOTOS_EXPORT_DB</span> <span class="o">=</span> <span class="s2">&quot;.osxphotos_export.db&quot;</span>
<span class="n">OSXPHOTOS_EXPORT_DB</span> <span class="o">=</span> <span class="s2">".osxphotos_export.db"</span>
<span class="c1"># bit flags for burst images (&quot;burstPickType&quot;)</span>
<span class="c1"># bit flags for burst images ("burstPickType")</span>
<span class="n">BURST_PICK_TYPE_NONE</span> <span class="o">=</span> <span class="mb">0b0</span> <span class="c1"># 0: sometimes used for single images with a burst UUID</span>
<span class="n">BURST_NOT_SELECTED</span> <span class="o">=</span> <span class="mb">0b10</span> <span class="c1"># 2: burst image is not selected</span>
<span class="n">BURST_DEFAULT_PICK</span> <span class="o">=</span> <span class="mb">0b100</span> <span class="c1"># 4: burst image is the one Photos picked to be key image before any selections made</span>
@@ -304,32 +467,32 @@
<span class="n">BURST_KEY</span> <span class="o">=</span> <span class="mb">0b10000</span> <span class="c1"># 16: burst image is the key photo (top of burst stack)</span>
<span class="n">BURST_UNKNOWN</span> <span class="o">=</span> <span class="mb">0b100000</span> <span class="c1"># 32: this is almost always set with BURST_DEFAULT_PICK and never if BURST_DEFAULT_PICK is not set. I think this has something to do with what algorithm Photos used to pick the default image</span>
<span class="n">LIVE_VIDEO_EXTENSIONS</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;.mov&quot;</span><span class="p">]</span>
<span class="n">LIVE_VIDEO_EXTENSIONS</span> <span class="o">=</span> <span class="p">[</span><span class="s2">".mov"</span><span class="p">]</span>
<span class="c1"># categories that --post-command can be used with; these map to ExportResults fields</span>
<span class="n">POST_COMMAND_CATEGORIES</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">&quot;exported&quot;</span><span class="p">:</span> <span class="s2">&quot;All exported files&quot;</span><span class="p">,</span>
<span class="s2">&quot;new&quot;</span><span class="p">:</span> <span class="s2">&quot;When used with &#39;--update&#39;, all newly exported files&quot;</span><span class="p">,</span>
<span class="s2">&quot;updated&quot;</span><span class="p">:</span> <span class="s2">&quot;When used with &#39;--update&#39;, all files which were previously exported but updated this time&quot;</span><span class="p">,</span>
<span class="s2">&quot;skipped&quot;</span><span class="p">:</span> <span class="s2">&quot;When used with &#39;--update&#39;, all files which were skipped (because they were previously exported and didn&#39;t change)&quot;</span><span class="p">,</span>
<span class="s2">&quot;missing&quot;</span><span class="p">:</span> <span class="s2">&quot;All files which were not exported because they were missing from the Photos library&quot;</span><span class="p">,</span>
<span class="s2">&quot;exif_updated&quot;</span><span class="p">:</span> <span class="s2">&quot;When used with &#39;--exiftool&#39;, all files on which exiftool updated the metadata&quot;</span><span class="p">,</span>
<span class="s2">&quot;touched&quot;</span><span class="p">:</span> <span class="s2">&quot;When used with &#39;--touch-file&#39;, all files where the date was touched&quot;</span><span class="p">,</span>
<span class="s2">&quot;converted_to_jpeg&quot;</span><span class="p">:</span> <span class="s2">&quot;When used with &#39;--convert-to-jpeg&#39;, all files which were converted to jpeg&quot;</span><span class="p">,</span>
<span class="s2">&quot;sidecar_json_written&quot;</span><span class="p">:</span> <span class="s2">&quot;When used with &#39;--sidecar json&#39;, all JSON sidecar files which were written&quot;</span><span class="p">,</span>
<span class="s2">&quot;sidecar_json_skipped&quot;</span><span class="p">:</span> <span class="s2">&quot;When used with &#39;--sidecar json&#39; and &#39;--update&#39;, all JSON sidecar files which were skipped&quot;</span><span class="p">,</span>
<span class="s2">&quot;sidecar_exiftool_written&quot;</span><span class="p">:</span> <span class="s2">&quot;When used with &#39;--sidecar exiftool&#39;, all exiftool sidecar files which were written&quot;</span><span class="p">,</span>
<span class="s2">&quot;sidecar_exiftool_skipped&quot;</span><span class="p">:</span> <span class="s2">&quot;When used with &#39;--sidecar exiftool&#39; and &#39;--update, all exiftool sidecar files which were skipped&quot;</span><span class="p">,</span>
<span class="s2">&quot;sidecar_xmp_written&quot;</span><span class="p">:</span> <span class="s2">&quot;When used with &#39;--sidecar xmp&#39;, all XMP sidecar files which were written&quot;</span><span class="p">,</span>
<span class="s2">&quot;sidecar_xmp_skipped&quot;</span><span class="p">:</span> <span class="s2">&quot;When used with &#39;--sidecar xmp&#39; and &#39;--update&#39;, all XMP sidecar files which were skipped&quot;</span><span class="p">,</span>
<span class="s2">&quot;error&quot;</span><span class="p">:</span> <span class="s2">&quot;All files which produced an error during export&quot;</span><span class="p">,</span>
<span class="c1"># &quot;deleted_files&quot;: &quot;When used with &#39;--cleanup&#39;, all files deleted during the export&quot;,</span>
<span class="c1"># &quot;deleted_directories&quot;: &quot;When used with &#39;--cleanup&#39;, all directories deleted during the export&quot;,</span>
<span class="s2">"exported"</span><span class="p">:</span> <span class="s2">"All exported files"</span><span class="p">,</span>
<span class="s2">"new"</span><span class="p">:</span> <span class="s2">"When used with '--update', all newly exported files"</span><span class="p">,</span>
<span class="s2">"updated"</span><span class="p">:</span> <span class="s2">"When used with '--update', all files which were previously exported but updated this time"</span><span class="p">,</span>
<span class="s2">"skipped"</span><span class="p">:</span> <span class="s2">"When used with '--update', all files which were skipped (because they were previously exported and didn't change)"</span><span class="p">,</span>
<span class="s2">"missing"</span><span class="p">:</span> <span class="s2">"All files which were not exported because they were missing from the Photos library"</span><span class="p">,</span>
<span class="s2">"exif_updated"</span><span class="p">:</span> <span class="s2">"When used with '--exiftool', all files on which exiftool updated the metadata"</span><span class="p">,</span>
<span class="s2">"touched"</span><span class="p">:</span> <span class="s2">"When used with '--touch-file', all files where the date was touched"</span><span class="p">,</span>
<span class="s2">"converted_to_jpeg"</span><span class="p">:</span> <span class="s2">"When used with '--convert-to-jpeg', all files which were converted to jpeg"</span><span class="p">,</span>
<span class="s2">"sidecar_json_written"</span><span class="p">:</span> <span class="s2">"When used with '--sidecar json', all JSON sidecar files which were written"</span><span class="p">,</span>
<span class="s2">"sidecar_json_skipped"</span><span class="p">:</span> <span class="s2">"When used with '--sidecar json' and '--update', all JSON sidecar files which were skipped"</span><span class="p">,</span>
<span class="s2">"sidecar_exiftool_written"</span><span class="p">:</span> <span class="s2">"When used with '--sidecar exiftool', all exiftool sidecar files which were written"</span><span class="p">,</span>
<span class="s2">"sidecar_exiftool_skipped"</span><span class="p">:</span> <span class="s2">"When used with '--sidecar exiftool' and '--update, all exiftool sidecar files which were skipped"</span><span class="p">,</span>
<span class="s2">"sidecar_xmp_written"</span><span class="p">:</span> <span class="s2">"When used with '--sidecar xmp', all XMP sidecar files which were written"</span><span class="p">,</span>
<span class="s2">"sidecar_xmp_skipped"</span><span class="p">:</span> <span class="s2">"When used with '--sidecar xmp' and '--update', all XMP sidecar files which were skipped"</span><span class="p">,</span>
<span class="s2">"error"</span><span class="p">:</span> <span class="s2">"All files which produced an error during export"</span><span class="p">,</span>
<span class="c1"># "deleted_files": "When used with '--cleanup', all files deleted during the export",</span>
<span class="c1"># "deleted_directories": "When used with '--cleanup', all directories deleted during the export",</span>
<span class="p">}</span>
<div class="viewcode-block" id="AlbumSortOrder"><a class="viewcode-back" href="../../reference.html#osxphotos.AlbumSortOrder">[docs]</a><span class="k">class</span> <span class="nc">AlbumSortOrder</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Album Sort Order&quot;&quot;&quot;</span>
<span class="sd">"""Album Sort Order"""</span>
<span class="n">UNKNOWN</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">MANUAL</span> <span class="o">=</span> <span class="mi">1</span>
@@ -342,88 +505,61 @@
<span class="c1"># stat sort order for cProfile: https://docs.python.org/3/library/profile.html#pstats.Stats.sort_stats</span>
<span class="n">PROFILE_SORT_KEYS</span> <span class="o">=</span> <span class="p">[</span>
<span class="s2">&quot;calls&quot;</span><span class="p">,</span>
<span class="s2">&quot;cumulative&quot;</span><span class="p">,</span>
<span class="s2">&quot;cumtime&quot;</span><span class="p">,</span>
<span class="s2">&quot;file&quot;</span><span class="p">,</span>
<span class="s2">&quot;filename&quot;</span><span class="p">,</span>
<span class="s2">&quot;module&quot;</span><span class="p">,</span>
<span class="s2">&quot;ncalls&quot;</span><span class="p">,</span>
<span class="s2">&quot;pcalls&quot;</span><span class="p">,</span>
<span class="s2">&quot;line&quot;</span><span class="p">,</span>
<span class="s2">&quot;name&quot;</span><span class="p">,</span>
<span class="s2">&quot;nfl&quot;</span><span class="p">,</span>
<span class="s2">&quot;stdname&quot;</span><span class="p">,</span>
<span class="s2">&quot;time&quot;</span><span class="p">,</span>
<span class="s2">&quot;tottime&quot;</span><span class="p">,</span>
<span class="s2">"calls"</span><span class="p">,</span>
<span class="s2">"cumulative"</span><span class="p">,</span>
<span class="s2">"cumtime"</span><span class="p">,</span>
<span class="s2">"file"</span><span class="p">,</span>
<span class="s2">"filename"</span><span class="p">,</span>
<span class="s2">"module"</span><span class="p">,</span>
<span class="s2">"ncalls"</span><span class="p">,</span>
<span class="s2">"pcalls"</span><span class="p">,</span>
<span class="s2">"line"</span><span class="p">,</span>
<span class="s2">"name"</span><span class="p">,</span>
<span class="s2">"nfl"</span><span class="p">,</span>
<span class="s2">"stdname"</span><span class="p">,</span>
<span class="s2">"time"</span><span class="p">,</span>
<span class="s2">"tottime"</span><span class="p">,</span>
<span class="p">]</span>
</pre></div>
</div>
</article>
</div>
<footer>
<div class="related-pages">
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h1 class="logo"><a href="../../index.html">osxphotos</a></h1>
<h3>Navigation</h3>
<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">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="../../reference.html">osxphotos package</a></li>
</ul>
<div class="relations">
<h3>Related Topics</h3>
<ul>
<li><a href="../../index.html">Documentation overview</a><ul>
<li><a href="../index.html">Module code</a><ul>
</ul></li>
</ul></li>
</ul>
</div>
<div id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<div class="bottom-of-page">
<div class="left-details">
<div class="copyright">
Copyright &#169; 2021, Rhet Turnbull
</div>
Made with <a href="https://www.sphinx-doc.org/">Sphinx</a> and <a class="muted-link" href="https://pradyunsg.me">@pradyunsg</a>'s
<a href="https://github.com/pradyunsg/furo">Furo</a>
</div>
<div class="right-details">
<div class="icons">
</div>
</div>
</div>
</div>
<div class="clearer"></div>
</footer>
</div>
<div class="footer">
&copy;2021, Rhet Turnbull.
<aside class="toc-drawer no-toc">
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
</div>
</body>
</aside>
</div>
</div><script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
<script src="../../_static/jquery.js"></script>
<script src="../../_static/underscore.js"></script>
<script src="../../_static/doctools.js"></script>
<script src="../../_static/scripts/furo.js"></script>
<script src="../../_static/clipboard.min.js"></script>
<script src="../../_static/copybutton.js"></script>
</body>
</html>

View File

@@ -1,173 +1,325 @@
<!doctype html>
<html class="no-js">
<head><meta charset="utf-8"/>
<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" />
<!DOCTYPE html>
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
<title>osxphotos.momentinfo - 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" />
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>osxphotos.momentinfo &#8212; osxphotos 0.47.9 documentation</title>
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../../_static/alabaster.css" />
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
<script src="../../_static/jquery.js"></script>
<script src="../../_static/underscore.js"></script>
<script src="../../_static/doctools.js"></script>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
<link rel="stylesheet" href="../../_static/custom.css" type="text/css" />
<style>
body {
--color-code-background: #f8f8f8;
--color-code-foreground: black;
}
@media not print {
body[data-theme="dark"] {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
}
@media (prefers-color-scheme: dark) {
body:not([data-theme="light"]) {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
}
}
}
</style></head>
<body>
<script>
document.body.dataset.theme = localStorage.getItem("theme") || "auto";
</script>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-toc" viewBox="0 0 24 24">
<title>Contents</title>
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 1024 1024">
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM115.4 518.9L271.7 642c5.8 4.6 14.4.5 14.4-6.9V388.9c0-7.4-8.5-11.5-14.4-6.9L115.4 505.1a8.74 8.74 0 0 0 0 13.8z"/>
</svg>
</symbol>
<symbol id="svg-menu" viewBox="0 0 24 24">
<title>Menu</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-menu">
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</symbol>
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
<title>Expand</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-chevron-right">
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24">
<title>Light mode</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather-sun">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24">
<title>Dark mode</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-moon">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" />
</svg>
</symbol>
<symbol id="svg-sun-half" viewBox="0 0 24 24">
<title>Auto light/dark mode</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-shadow">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="12" cy="12" r="9" />
<path d="M13 12h5" />
<path d="M13 15h4" />
<path d="M13 18h1" />
<path d="M13 9h4" />
<path d="M13 6h1" />
</svg>
</symbol>
</svg>
<input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation">
<input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc">
<label class="overlay sidebar-overlay" for="__navigation">
<div class="visually-hidden">Hide navigation sidebar</div>
</label>
<label class="overlay toc-overlay" for="__toc">
<div class="visually-hidden">Hide table of contents sidebar</div>
</label>
<div class="page">
<header class="mobile-header">
<div class="header-left">
<label class="nav-overlay-icon" for="__navigation">
<div class="visually-hidden">Toggle site navigation sidebar</div>
<i class="icon"><svg><use href="#svg-menu"></use></svg></i>
</label>
</div>
<div class="header-center">
<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">
<button class="theme-toggle">
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
</button>
</div>
<label class="toc-overlay-icon toc-header-icon no-toc" for="__toc">
<div class="visually-hidden">Toggle table of contents sidebar</div>
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
</label>
</div>
</header>
<aside class="sidebar-drawer">
<div class="sidebar-container">
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
</head><body>
<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">
<input type="hidden" name="check_keywords" value="yes">
<input type="hidden" name="area" value="default">
</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="../../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 class="document">
<div class="documentwrapper">
<div class="bodywrapper">
</div>
</div>
<div class="body" role="main">
<h1>Source code for osxphotos.momentinfo</h1><div class="highlight"><pre>
<span></span><span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;MomentInfo&quot;</span><span class="p">]</span>
<span class="sd">&quot;&quot;&quot;MomentInfo class with details about photo moments.&quot;&quot;&quot;</span>
</div>
</div>
</aside>
<div class="main">
<div class="content">
<div class="article-container">
<a href="#" class="back-to-top muted-link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z"></path>
</svg>
<span>Back to top</span>
</a>
<div class="content-icon-container"><div class="theme-toggle-container theme-toggle-content">
<button class="theme-toggle">
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
</button>
</div>
<label class="toc-overlay-icon toc-content-icon no-toc" for="__toc">
<div class="visually-hidden">Toggle table of contents sidebar</div>
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
</label>
</div>
<article role="main">
<h1>Source code for osxphotos.momentinfo</h1><div class="highlight"><pre>
<span></span><span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"MomentInfo"</span><span class="p">]</span>
<span class="sd">"""MomentInfo class with details about photo moments."""</span>
<div class="viewcode-block" id="MomentInfo"><a class="viewcode-back" href="../../reference.html#osxphotos.MomentInfo">[docs]</a><span class="k">class</span> <span class="nc">MomentInfo</span><span class="p">:</span>
<span class="sd">&quot;&quot;&quot;Info about a photo moment&quot;&quot;&quot;</span>
<span class="sd">"""Info about a photo moment"""</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">db</span><span class="p">,</span> <span class="n">moment_pk</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Initialize with a moment PK; returns None if PK not found.&quot;&quot;&quot;</span>
<span class="sd">"""Initialize with a moment PK; returns None if PK not found."""</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_db</span> <span class="o">=</span> <span class="n">db</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_pk</span> <span class="o">=</span> <span class="n">moment_pk</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_moment</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_db_moment_pk</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">moment_pk</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">_moment</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;No moment with PK </span><span class="si">{</span><span class="n">moment_pk</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"No moment with PK </span><span class="si">{</span><span class="n">moment_pk</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">pk</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Primary key of the moment.&quot;&quot;&quot;</span>
<span class="sd">"""Primary key of the moment."""</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pk</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">location</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Location of the moment.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;latitude&quot;</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;longitude&quot;</span><span class="p">))</span>
<span class="sd">"""Location of the moment."""</span>
<span class="k">return</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"latitude"</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"longitude"</span><span class="p">))</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">title</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Title of the moment.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;title&quot;</span><span class="p">)</span>
<span class="sd">"""Title of the moment."""</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"title"</span><span class="p">)</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">subtitle</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Subtitle of the moment.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;subtitle&quot;</span><span class="p">)</span>
<span class="sd">"""Subtitle of the moment."""</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"subtitle"</span><span class="p">)</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">start_date</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Start date of the moment.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;startDate&quot;</span><span class="p">)</span>
<span class="sd">"""Start date of the moment."""</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"startDate"</span><span class="p">)</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">end_date</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Stop date of the moment.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;endDate&quot;</span><span class="p">)</span>
<span class="sd">"""Stop date of the moment."""</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"endDate"</span><span class="p">)</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">date</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Date of the moment.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;representativeDate&quot;</span><span class="p">)</span>
<span class="sd">"""Date of the moment."""</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"representativeDate"</span><span class="p">)</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">modification_date</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Modification date of the moment.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;modificationDate&quot;</span><span class="p">)</span>
<span class="sd">"""Modification date of the moment."""</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"modificationDate"</span><span class="p">)</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">photos</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;All photos in this moment&quot;&quot;&quot;</span>
<span class="sd">"""All photos in this moment"""</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photos</span>
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
<span class="n">photo_uuids</span> <span class="o">=</span> <span class="p">[</span>
<span class="n">uuid</span>
<span class="k">for</span> <span class="n">uuid</span><span class="p">,</span> <span class="n">photo</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbphotos</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
<span class="k">if</span> <span class="n">photo</span><span class="p">[</span><span class="s2">&quot;momentID&quot;</span><span class="p">]</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pk</span>
<span class="k">if</span> <span class="n">photo</span><span class="p">[</span><span class="s2">"momentID"</span><span class="p">]</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pk</span>
<span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_photos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">photos_by_uuid</span><span class="p">(</span><span class="n">photo_uuids</span><span class="p">)</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photos</span></div>
</pre></div>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photos</span>
</div>
<div class="viewcode-block" id="MomentInfo.asdict"><a class="viewcode-back" href="../../reference.html#osxphotos.MomentInfo.asdict">[docs]</a> <span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Returns all moment info as dictionary"""</span>
<span class="k">return</span> <span class="p">{</span>
<span class="s2">"pk"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">pk</span><span class="p">,</span>
<span class="s2">"location"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">location</span><span class="p">,</span>
<span class="s2">"title"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">,</span>
<span class="s2">"subtitle"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">subtitle</span><span class="p">,</span>
<span class="s2">"start_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">start_date</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">start_date</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
<span class="s2">"end_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">end_date</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">end_date</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
<span class="s2">"date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">date</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
<span class="s2">"modification_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">modification_date</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">modification_date</span>
<span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
<span class="s2">"photos"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">photos</span><span class="p">,</span>
<span class="p">}</span></div></div>
</pre></div>
</article>
</div>
<footer>
<div class="related-pages">
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h1 class="logo"><a href="../../index.html">osxphotos</a></h1>
<h3>Navigation</h3>
<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">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="../../reference.html">osxphotos package</a></li>
</ul>
<div class="relations">
<h3>Related Topics</h3>
<ul>
<li><a href="../../index.html">Documentation overview</a><ul>
<li><a href="../index.html">Module code</a><ul>
</ul></li>
</ul></li>
</ul>
</div>
<div id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<div class="bottom-of-page">
<div class="left-details">
<div class="copyright">
Copyright &#169; 2021, Rhet Turnbull
</div>
Made with <a href="https://www.sphinx-doc.org/">Sphinx</a> and <a class="muted-link" href="https://pradyunsg.me">@pradyunsg</a>'s
<a href="https://github.com/pradyunsg/furo">Furo</a>
</div>
<div class="right-details">
<div class="icons">
</div>
</div>
</div>
</div>
<div class="clearer"></div>
</footer>
</div>
<div class="footer">
&copy;2021, Rhet Turnbull.
<aside class="toc-drawer no-toc">
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
</div>
</body>
</aside>
</div>
</div><script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
<script src="../../_static/jquery.js"></script>
<script src="../../_static/underscore.js"></script>
<script src="../../_static/doctools.js"></script>
<script src="../../_static/scripts/furo.js"></script>
<script src="../../_static/clipboard.min.js"></script>
<script src="../../_static/copybutton.js"></script>
</body>
</html>

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.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>

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.photoinfo - osxphotos 0.47.9 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.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>
@@ -206,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>
@@ -249,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>
@@ -674,7 +676,7 @@
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_faceinfo</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">moment</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">moment_info</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Moment photo belongs to"""</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span>
@@ -1551,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>

File diff suppressed because it is too large Load Diff

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.phototemplate - osxphotos 0.47.10 documentation</title>
<title>osxphotos.phototemplate - 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.10 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.10 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,12 +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="../../template_help.html">osxphotos Template System</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>
@@ -334,6 +334,7 @@
<span class="s2">"</span><span class="si">{exif.camera_make}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Camera make from original photo's EXIF information as imported by Photos, e.g. 'Apple'"</span><span class="p">,</span>
<span class="s2">"</span><span class="si">{exif.camera_model}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Camera model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s'"</span><span class="p">,</span>
<span class="s2">"</span><span class="si">{exif.lens_model}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Lens model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s back camera 4.15mm f/2.2'"</span><span class="p">,</span>
<span class="s2">"</span><span class="si">{moment}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"The moment title of the photo"</span><span class="p">,</span>
<span class="s2">"</span><span class="si">{uuid}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Photo's internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'"</span><span class="p">,</span>
<span class="s2">"</span><span class="si">{id}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"A unique number for the photo based on its primary key in the Photos database. "</span>
<span class="o">+</span> <span class="s2">"A sequential integer, e.g. 1, 2, 3...etc. Each asset associated with a photo (e.g. an image and Live Photo preview) will share the same id. "</span>
@@ -1170,6 +1171,8 @@
<span class="n">value</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">exif_info</span><span class="o">.</span><span class="n">camera_model</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">exif_info</span> <span class="k">else</span> <span class="kc">None</span>
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"exif.lens_model"</span><span class="p">:</span>
<span class="n">value</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">exif_info</span><span class="o">.</span><span class="n">lens_model</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">exif_info</span> <span class="k">else</span> <span class="kc">None</span>
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"moment"</span><span class="p">:</span>
<span class="n">value</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">moment_info</span><span class="o">.</span><span class="n">title</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">moment_info</span> <span class="k">else</span> <span class="kc">None</span>
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"uuid"</span><span class="p">:</span>
<span class="n">value</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">uuid</span>
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"id"</span><span class="p">:</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.queryoptions - osxphotos 0.47.9 documentation</title>
<title>osxphotos.queryoptions - 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>
@@ -210,158 +211,163 @@
<span class="sd">"""QueryOptions class for PhotosDB.query</span>
<span class="sd"> Attributes:</span>
<span class="sd"> keyword: list of keywords to search for</span>
<span class="sd"> person: list of person names to search for</span>
<span class="sd"> added_after: search for photos added after a given date</span>
<span class="sd"> added_before: search for photos added before a given date</span>
<span class="sd"> added_in_last: search for photos added in last X datetime.timedelta</span>
<span class="sd"> album: list of album names to search for</span>
<span class="sd"> folder: list of folder names to search for</span>
<span class="sd"> uuid: list of uuids to search for</span>
<span class="sd"> title: list of titles to search for</span>
<span class="sd"> no_title: search for photos with no title</span>
<span class="sd"> burst_photos: search for burst photos</span>
<span class="sd"> burst: search for burst photos</span>
<span class="sd"> cloudasset: search for photos that are managed by iCloud</span>
<span class="sd"> deleted_only: search only for deleted photos</span>
<span class="sd"> deleted: also include deleted photos</span>
<span class="sd"> description: list of descriptions to search for</span>
<span class="sd"> no_description: search for photos with no description</span>
<span class="sd"> ignore_case: ignore case when searching</span>
<span class="sd"> duplicate: search for duplicate photos</span>
<span class="sd"> edited: search for edited photos</span>
<span class="sd"> exif: search for photos with EXIF tags that matches the given data</span>
<span class="sd"> external_edit: search for photos edited in external apps</span>
<span class="sd"> favorite: search for favorite photos</span>
<span class="sd"> not_favorite: search for non-favorite photos</span>
<span class="sd"> hidden: search for hidden photos</span>
<span class="sd"> not_hidden: search for non-hidden photos</span>
<span class="sd"> missing: search for missing photos</span>
<span class="sd"> not_missing: search for non-missing photos</span>
<span class="sd"> shared: search for shared photos</span>
<span class="sd"> not_shared: search for non-shared photos</span>
<span class="sd"> photos: search for photos</span>
<span class="sd"> movies: search for movies</span>
<span class="sd"> uti: list of UTIs to search for</span>
<span class="sd"> burst: search for burst photos</span>
<span class="sd"> not_burst: search for non-burst photos</span>
<span class="sd"> live: search for live photos</span>
<span class="sd"> not_live: search for non-live photos</span>
<span class="sd"> cloudasset: search for photos that are managed by iCloud</span>
<span class="sd"> not_cloudasset: search for photos that are not managed by iCloud</span>
<span class="sd"> incloud: search for cloud assets that are synched to iCloud</span>
<span class="sd"> not_incloud: search for cloud asset photos that are not yet synched to iCloud</span>
<span class="sd"> folder: list of folder names to search for</span>
<span class="sd"> from_date: search for photos taken on or after this date</span>
<span class="sd"> to_date: search for photos taken on or before this date</span>
<span class="sd"> portrait: search for portrait photos</span>
<span class="sd"> not_portrait: search for non-portrait photos</span>
<span class="sd"> screenshot: search for screenshot photos</span>
<span class="sd"> not_screenshot: search for non-screenshot photos</span>
<span class="sd"> slow_mo: search for slow-mo photos</span>
<span class="sd"> not_slow_mo: search for non-slow-mo photos</span>
<span class="sd"> time_lapse: search for time-lapse photos</span>
<span class="sd"> not_time_lapse: search for non-time-lapse photos</span>
<span class="sd"> hdr: search for HDR photos</span>
<span class="sd"> not_hdr: search for non-HDR photos</span>
<span class="sd"> selfie: search for selfie photos</span>
<span class="sd"> not_selfie: search for non-selfie photos</span>
<span class="sd"> panorama: search for panorama photos</span>
<span class="sd"> not_panorama: search for non-panorama photos</span>
<span class="sd"> has_raw: search for photos with associated raw files</span>
<span class="sd"> place: list of place names to search for</span>
<span class="sd"> no_place: search for photos with no place</span>
<span class="sd"> label: list of labels to search for</span>
<span class="sd"> deleted: also include deleted photos</span>
<span class="sd"> deleted_only: search only for deleted photos</span>
<span class="sd"> has_comment: search for photos with comments</span>
<span class="sd"> no_comment: search for photos with no comments</span>
<span class="sd"> has_likes: search for shared photos with likes</span>
<span class="sd"> no_likes: search for shared photos with no likes</span>
<span class="sd"> is_reference: search for photos stored by reference (that is, they are not managed by Photos)</span>
<span class="sd"> in_album: search for photos in an album</span>
<span class="sd"> not_in_album: search for photos not in an album</span>
<span class="sd"> burst_photos: search for burst photos</span>
<span class="sd"> missing_bursts: for burst photos, also include burst photos that are missing</span>
<span class="sd"> name: list of names to search for</span>
<span class="sd"> min_size: minimum size of photos to search for</span>
<span class="sd"> max_size: maximum size of photos to search for</span>
<span class="sd"> regex: list of regular expressions to search for</span>
<span class="sd"> query_eval: list of query expressions to evaluate</span>
<span class="sd"> duplicate: search for duplicate photos</span>
<span class="sd"> location: search for photos with a location</span>
<span class="sd"> no_location: search for photos with no location</span>
<span class="sd"> function: list of query functions to evaluate</span>
<span class="sd"> has_comment: search for photos with comments</span>
<span class="sd"> has_likes: search for shared photos with likes</span>
<span class="sd"> has_raw: search for photos with associated raw files</span>
<span class="sd"> hdr: search for HDR photos</span>
<span class="sd"> hidden: search for hidden photos</span>
<span class="sd"> ignore_case: ignore case when searching</span>
<span class="sd"> in_album: search for photos in an album</span>
<span class="sd"> incloud: search for cloud assets that are synched to iCloud</span>
<span class="sd"> is_reference: search for photos stored by reference (that is, they are not managed by Photos)</span>
<span class="sd"> keyword: list of keywords to search for</span>
<span class="sd"> label: list of labels to search for</span>
<span class="sd"> live: search for live photos</span>
<span class="sd"> location: search for photos with a location</span>
<span class="sd"> max_size: maximum size of photos to search for</span>
<span class="sd"> min_size: minimum size of photos to search for</span>
<span class="sd"> missing_bursts: for burst photos, also include burst photos that are missing</span>
<span class="sd"> missing: search for missing photos</span>
<span class="sd"> movies: search for movies</span>
<span class="sd"> name: list of names to search for</span>
<span class="sd"> no_comment: search for photos with no comments</span>
<span class="sd"> no_description: search for photos with no description</span>
<span class="sd"> no_likes: search for shared photos with no likes</span>
<span class="sd"> no_location: search for photos with no location</span>
<span class="sd"> no_place: search for photos with no place</span>
<span class="sd"> no_title: search for photos with no title</span>
<span class="sd"> not_burst: search for non-burst photos</span>
<span class="sd"> not_cloudasset: search for photos that are not managed by iCloud</span>
<span class="sd"> not_favorite: search for non-favorite photos</span>
<span class="sd"> not_hdr: search for non-HDR photos</span>
<span class="sd"> not_hidden: search for non-hidden photos</span>
<span class="sd"> not_in_album: search for photos not in an album</span>
<span class="sd"> not_incloud: search for cloud asset photos that are not yet synched to iCloud</span>
<span class="sd"> not_live: search for non-live photos</span>
<span class="sd"> not_missing: search for non-missing photos</span>
<span class="sd"> not_panorama: search for non-panorama photos</span>
<span class="sd"> not_portrait: search for non-portrait photos</span>
<span class="sd"> not_screenshot: search for non-screenshot photos</span>
<span class="sd"> not_selfie: search for non-selfie photos</span>
<span class="sd"> not_shared: search for non-shared photos</span>
<span class="sd"> not_slow_mo: search for non-slow-mo photos</span>
<span class="sd"> not_time_lapse: search for non-time-lapse photos</span>
<span class="sd"> panorama: search for panorama photos</span>
<span class="sd"> person: list of person names to search for</span>
<span class="sd"> photos: search for photos</span>
<span class="sd"> place: list of place names to search for</span>
<span class="sd"> portrait: search for portrait photos</span>
<span class="sd"> query_eval: list of query expressions to evaluate</span>
<span class="sd"> regex: list of regular expressions to search for</span>
<span class="sd"> screenshot: search for screenshot photos</span>
<span class="sd"> selected: search for selected photos</span>
<span class="sd"> exif: search for photos with EXIF tags that matches the given data</span>
<span class="sd"> selfie: search for selfie photos</span>
<span class="sd"> shared: search for shared photos</span>
<span class="sd"> slow_mo: search for slow-mo photos</span>
<span class="sd"> time_lapse: search for time-lapse photos</span>
<span class="sd"> title: list of titles to search for</span>
<span class="sd"> to_date: search for photos taken on or before this date</span>
<span class="sd"> uti: list of UTIs to search for</span>
<span class="sd"> uuid: list of uuids to search for</span>
<span class="sd"> year: search for photos taken in a given year</span>
<span class="sd"> """</span>
<span class="n">keyword</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">person</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">added_after</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">added_before</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">added_in_last</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">timedelta</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">album</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">folder</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">uuid</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">title</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">no_title</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">burst_photos</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">burst</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">cloudasset</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">deleted_only</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">deleted</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">description</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">no_description</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">ignore_case</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">duplicate</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">edited</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">exif</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="nb">str</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="n">external_edit</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">favorite</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_favorite</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">hidden</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_hidden</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">missing</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_missing</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">shared</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_shared</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">photos</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">movies</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">uti</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">burst</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_burst</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">live</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_live</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">cloudasset</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_cloudasset</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">incloud</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_incloud</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">folder</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">from_date</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">to_date</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">from_time</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">time</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">to_time</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">time</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">portrait</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_portrait</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">screenshot</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_screenshot</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">slow_mo</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_slow_mo</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">time_lapse</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_time_lapse</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">hdr</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_hdr</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">selfie</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_selfie</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">panorama</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_panorama</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">has_raw</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">place</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">no_place</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">label</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">deleted</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">deleted_only</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">has_comment</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">no_comment</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">has_likes</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">no_likes</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">is_reference</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">in_album</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_in_album</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">burst_photos</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">missing_bursts</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">name</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">min_size</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">bitmath</span><span class="o">.</span><span class="n">Byte</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">max_size</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">bitmath</span><span class="o">.</span><span class="n">Byte</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">regex</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="nb">str</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="n">query_eval</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">duplicate</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">location</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">no_location</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">function</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="n">callable</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="n">has_comment</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">has_likes</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">has_raw</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">hdr</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">hidden</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">ignore_case</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">in_album</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">incloud</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">is_reference</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">keyword</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">label</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">live</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">location</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">max_size</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">bitmath</span><span class="o">.</span><span class="n">Byte</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">min_size</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">bitmath</span><span class="o">.</span><span class="n">Byte</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">missing_bursts</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">missing</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">movies</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">name</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">no_comment</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">no_description</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">no_likes</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">no_location</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">no_place</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">no_title</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_burst</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_cloudasset</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_favorite</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_hdr</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_hidden</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_in_album</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_incloud</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_live</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_missing</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_panorama</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_portrait</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_screenshot</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_selfie</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_shared</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_slow_mo</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">not_time_lapse</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">panorama</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">person</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">photos</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">place</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">portrait</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">query_eval</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">regex</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="nb">str</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="n">screenshot</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">selected</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">exif</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="nb">str</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="n">selfie</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">shared</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">slow_mo</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">time_lapse</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">title</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">to_date</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">to_time</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">time</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">uti</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">uuid</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</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="n">year</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</span><span class="p">[</span><span class="nb">int</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>

View File

@@ -281,6 +281,8 @@ Template Substitutions
- Camera model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s'
* - {exif.lens_model}
- Lens model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s back camera 4.15mm f/2.2'
* - {moment}
- The moment title of the photo
* - {uuid}
- Photo's internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'
* - {id}
@@ -318,7 +320,7 @@ Template Substitutions
* - {crlf}
- a carriage return + line feed: '\r\n'
* - {osxphotos_version}
- The osxphotos version, e.g. '0.48.1'
- The osxphotos version, e.g. '0.48.4'
* - {osxphotos_cmd_line}
- The full command line used to run osxphotos
* - {album}

View File

@@ -297,6 +297,10 @@ You can also export photos in a certain date range:
``osxphotos export /path/to/export --from-date "2020-01-01" --to-date "2020-02-28"``
or photos added to the library in the last week:
``osxphotos export /path/to/export --added-in-last "1 week"``
Converting images to JPEG on export
-----------------------------------

View File

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

View File

@@ -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.1 documentation</title>
<title>OSXPhotos Command Line Interface (CLI) - osxphotos 0.48.4 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.1 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.48.4 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.1 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.48.4 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">
@@ -205,7 +205,7 @@
<p class="rubric">Options</p>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-db">
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;Photos</span> <span class="pre">database</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-db" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;PHOTOS_LIBRARY_PATH&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-db" title="Permalink to this definition">#</a></dt>
<dd><p>Specify Photos database path. Path to Photos library/database can be specified using either db or directly as PHOTOS_LIBRARY positional argument. If neither db or PHOTOS_LIBRARY provided, will attempt to find the library to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary</p>
</dd></dl>
<dl class="std option">
@@ -234,7 +234,7 @@
<p class="rubric">Options</p>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-albums-db">
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;Photos</span> <span class="pre">database</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-albums-db" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;PHOTOS_LIBRARY_PATH&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-albums-db" title="Permalink to this definition">#</a></dt>
<dd><p>Specify Photos database path. Path to Photos library/database can be specified using either db or directly as PHOTOS_LIBRARY positional argument. If neither db or PHOTOS_LIBRARY provided, will attempt to find the library to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary</p>
</dd></dl>
<dl class="std option">
@@ -277,7 +277,7 @@ library specified by db to the database specified by DB2</p>
<p class="rubric">Options</p>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-diff-db">
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;Photos</span> <span class="pre">database</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-diff-db" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;PHOTOS_LIBRARY_PATH&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-diff-db" title="Permalink to this definition">#</a></dt>
<dd><p>Specify Photos database path. Path to Photos library/database can be specified using either db or directly as PHOTOS_LIBRARY positional argument. If neither db or PHOTOS_LIBRARY provided, will attempt to find the library to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary</p>
</dd></dl>
<dl class="std option">
@@ -318,7 +318,7 @@ library specified by db to the database specified by DB2</p>
<p class="rubric">Options</p>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-dump-db">
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;Photos</span> <span class="pre">database</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-dump-db" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;PHOTOS_LIBRARY_PATH&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-dump-db" title="Permalink to this definition">#</a></dt>
<dd><p>Specify Photos database path. Path to Photos library/database can be specified using either db or directly as PHOTOS_LIBRARY positional argument. If neither db or PHOTOS_LIBRARY provided, will attempt to find the library to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary</p>
</dd></dl>
<dl class="std option">
@@ -361,7 +361,7 @@ to modify this behavior.</p>
<p class="rubric">Options</p>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-db">
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;Photos</span> <span class="pre">database</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-export-db" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;PHOTOS_LIBRARY_PATH&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-export-db" title="Permalink to this definition">#</a></dt>
<dd><p>Specify Photos database path. Path to Photos library/database can be specified using either db or directly as PHOTOS_LIBRARY positional argument. If neither db or PHOTOS_LIBRARY provided, will attempt to find the library to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary</p>
</dd></dl>
<dl class="std option">
@@ -640,6 +640,21 @@ to modify this behavior.</p>
<dd><p>Search for items from a specific year, e.g. year 2022 to find all photos from the year 2022. May be repeated to search multiple years.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-added-before">
<span class="sig-name descname"><span class="pre">--added-before</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;DATE&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-export-added-before" title="Permalink to this definition">#</a></dt>
<dd><p>Search for items added to the library before a specific date/time, e.g. added-before e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-added-after">
<span class="sig-name descname"><span class="pre">--added-after</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;DATE&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-export-added-after" title="Permalink to this definition">#</a></dt>
<dd><p>Search for items added to the libray after a specific date/time, e.g. added-after e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-added-in-last">
<span class="sig-name descname"><span class="pre">--added-in-last</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;TIME_DELTA&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-export-added-in-last" title="Permalink to this definition">#</a></dt>
<dd><p>Search for items added to the library in the last TIME_DELTA, where TIME_DELTA is a string like 12 hrs, 1 day, 1d, 1 week, 2weeks, 1 month, 1 year. for example, <cite>added-in-last 7d</cite> and <cite>added-in-last 1 week</cite> are equivalent. months are assumed to be 30 days and years are assumed to be 365 days. Common English abbreviations are accepted, e.g. d, day, days or m, min, minutes.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-has-comment">
<span class="sig-name descname"><span class="pre">--has-comment</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-export-has-comment" title="Permalink to this definition">#</a></dt>
<dd><p>Search for photos that have comments.</p>
@@ -983,7 +998,7 @@ to modify this behavior.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-report">
<span class="sig-name descname"><span class="pre">--report</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;path</span> <span class="pre">to</span> <span class="pre">export</span> <span class="pre">report&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-export-report" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--report</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;REPORT_FILE&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-export-report" title="Permalink to this definition">#</a></dt>
<dd><p>Write a CSV formatted report of all files that were exported.</p>
</dd></dl>
<dl class="std option">
@@ -1033,12 +1048,12 @@ to modify this behavior.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-load-config">
<span class="sig-name descname"><span class="pre">--load-config</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;config</span> <span class="pre">file</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-export-load-config" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--load-config</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;CONFIG_FILE&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-export-load-config" title="Permalink to this definition">#</a></dt>
<dd><p>Load options from file as written with save-config. This allows you to save a complex export command to file for later reuse. For example: osxphotos export &lt;lots of options here&gt; save-config osxphotos.toml then osxphotos export /path/to/export load-config osxphotos.toml. If any other command line options are used in conjunction with load-config, they will override the corresponding values in the config file.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-save-config">
<span class="sig-name descname"><span class="pre">--save-config</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;config</span> <span class="pre">file</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-export-save-config" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--save-config</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;CONFIG_FILE&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-export-save-config" title="Permalink to this definition">#</a></dt>
<dd><p>Save options to file for use with load-config. File format is TOML. See also config-only.</p>
</dd></dl>
<dl class="std option">
@@ -1095,7 +1110,7 @@ to modify this behavior.</p>
<p class="rubric">Options</p>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-info-db">
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;Photos</span> <span class="pre">database</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-info-db" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;PHOTOS_LIBRARY_PATH&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-info-db" title="Permalink to this definition">#</a></dt>
<dd><p>Specify Photos database path. Path to Photos library/database can be specified using either db or directly as PHOTOS_LIBRARY positional argument. If neither db or PHOTOS_LIBRARY provided, will attempt to find the library to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary</p>
</dd></dl>
<dl class="std option">
@@ -1138,7 +1153,7 @@ to modify this behavior.</p>
<p class="rubric">Options</p>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-keywords-db">
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;Photos</span> <span class="pre">database</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-keywords-db" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;PHOTOS_LIBRARY_PATH&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-keywords-db" title="Permalink to this definition">#</a></dt>
<dd><p>Specify Photos database path. Path to Photos library/database can be specified using either db or directly as PHOTOS_LIBRARY positional argument. If neither db or PHOTOS_LIBRARY provided, will attempt to find the library to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary</p>
</dd></dl>
<dl class="std option">
@@ -1162,7 +1177,7 @@ to modify this behavior.</p>
<p class="rubric">Options</p>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-labels-db">
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;Photos</span> <span class="pre">database</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-labels-db" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;PHOTOS_LIBRARY_PATH&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-labels-db" title="Permalink to this definition">#</a></dt>
<dd><p>Specify Photos database path. Path to Photos library/database can be specified using either db or directly as PHOTOS_LIBRARY positional argument. If neither db or PHOTOS_LIBRARY provided, will attempt to find the library to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary</p>
</dd></dl>
<dl class="std option">
@@ -1199,7 +1214,7 @@ to modify this behavior.</p>
<p class="rubric">Options</p>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-persons-db">
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;Photos</span> <span class="pre">database</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-persons-db" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;PHOTOS_LIBRARY_PATH&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-persons-db" title="Permalink to this definition">#</a></dt>
<dd><p>Specify Photos database path. Path to Photos library/database can be specified using either db or directly as PHOTOS_LIBRARY positional argument. If neither db or PHOTOS_LIBRARY provided, will attempt to find the library to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary</p>
</dd></dl>
<dl class="std option">
@@ -1223,7 +1238,7 @@ to modify this behavior.</p>
<p class="rubric">Options</p>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-places-db">
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;Photos</span> <span class="pre">database</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-places-db" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;PHOTOS_LIBRARY_PATH&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-places-db" title="Permalink to this definition">#</a></dt>
<dd><p>Specify Photos database path. Path to Photos library/database can be specified using either db or directly as PHOTOS_LIBRARY positional argument. If neither db or PHOTOS_LIBRARY provided, will attempt to find the library to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary</p>
</dd></dl>
<dl class="std option">
@@ -1249,7 +1264,7 @@ if more than one option is provided, they are treated as “AND”
<p class="rubric">Options</p>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-query-db">
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;Photos</span> <span class="pre">database</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-query-db" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;PHOTOS_LIBRARY_PATH&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-query-db" title="Permalink to this definition">#</a></dt>
<dd><p>Specify Photos database path. Path to Photos library/database can be specified using either db or directly as PHOTOS_LIBRARY positional argument. If neither db or PHOTOS_LIBRARY provided, will attempt to find the library to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary</p>
</dd></dl>
<dl class="std option">
@@ -1518,6 +1533,21 @@ if more than one option is provided, they are treated as “AND”
<dd><p>Search for items from a specific year, e.g. year 2022 to find all photos from the year 2022. May be repeated to search multiple years.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-query-added-before">
<span class="sig-name descname"><span class="pre">--added-before</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;DATE&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-query-added-before" title="Permalink to this definition">#</a></dt>
<dd><p>Search for items added to the library before a specific date/time, e.g. added-before e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-query-added-after">
<span class="sig-name descname"><span class="pre">--added-after</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;DATE&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-query-added-after" title="Permalink to this definition">#</a></dt>
<dd><p>Search for items added to the libray after a specific date/time, e.g. added-after e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-query-added-in-last">
<span class="sig-name descname"><span class="pre">--added-in-last</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;TIME_DELTA&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-query-added-in-last" title="Permalink to this definition">#</a></dt>
<dd><p>Search for items added to the library in the last TIME_DELTA, where TIME_DELTA is a string like 12 hrs, 1 day, 1d, 1 week, 2weeks, 1 month, 1 year. for example, <cite>added-in-last 7d</cite> and <cite>added-in-last 1 week</cite> are equivalent. months are assumed to be 30 days and years are assumed to be 365 days. Common English abbreviations are accepted, e.g. d, day, days or m, min, minutes.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-query-has-comment">
<span class="sig-name descname"><span class="pre">--has-comment</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-query-has-comment" title="Permalink to this definition">#</a></dt>
<dd><p>Search for photos that have comments.</p>
@@ -1653,7 +1683,7 @@ if more than one option is provided, they are treated as “AND”
<p class="rubric">Options</p>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-repl-db">
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;Photos</span> <span class="pre">database</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-repl-db" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;PHOTOS_LIBRARY_PATH&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-repl-db" title="Permalink to this definition">#</a></dt>
<dd><p>Specify Photos database path. Path to Photos library/database can be specified using either db or directly as PHOTOS_LIBRARY positional argument. If neither db or PHOTOS_LIBRARY provided, will attempt to find the library to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary</p>
</dd></dl>
<dl class="std option">
@@ -1922,6 +1952,21 @@ if more than one option is provided, they are treated as “AND”
<dd><p>Search for items from a specific year, e.g. year 2022 to find all photos from the year 2022. May be repeated to search multiple years.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-repl-added-before">
<span class="sig-name descname"><span class="pre">--added-before</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;DATE&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-repl-added-before" title="Permalink to this definition">#</a></dt>
<dd><p>Search for items added to the library before a specific date/time, e.g. added-before e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-repl-added-after">
<span class="sig-name descname"><span class="pre">--added-after</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;DATE&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-repl-added-after" title="Permalink to this definition">#</a></dt>
<dd><p>Search for items added to the libray after a specific date/time, e.g. added-after e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-repl-added-in-last">
<span class="sig-name descname"><span class="pre">--added-in-last</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;TIME_DELTA&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-repl-added-in-last" title="Permalink to this definition">#</a></dt>
<dd><p>Search for items added to the library in the last TIME_DELTA, where TIME_DELTA is a string like 12 hrs, 1 day, 1d, 1 week, 2weeks, 1 month, 1 year. for example, <cite>added-in-last 7d</cite> and <cite>added-in-last 1 week</cite> are equivalent. months are assumed to be 30 days and years are assumed to be 365 days. Common English abbreviations are accepted, e.g. d, day, days or m, min, minutes.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-repl-has-comment">
<span class="sig-name descname"><span class="pre">--has-comment</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-repl-has-comment" title="Permalink to this definition">#</a></dt>
<dd><p>Search for photos that have comments.</p>
@@ -2063,7 +2108,7 @@ uses /private/tmp/osxphotos_snapshots</p>
<p class="rubric">Options</p>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-snap-db">
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;Photos</span> <span class="pre">database</span> <span class="pre">path&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-snap-db" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">--db</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;PHOTOS_LIBRARY_PATH&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-snap-db" title="Permalink to this definition">#</a></dt>
<dd><p>Specify Photos database path. Path to Photos library/database can be specified using either db or directly as PHOTOS_LIBRARY positional argument. If neither db or PHOTOS_LIBRARY provided, will attempt to find the library to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary</p>
</dd></dl>
</section>
@@ -2226,6 +2271,11 @@ See Timewarp Overview below for additional information.</p>
<span class="sig-name descname"><span class="pre">--plain</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-timewarp-plain" title="Permalink to this definition">#</a></dt>
<dd><p>Plain text mode. Do not use rich output.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-timewarp-force">
<span class="sig-name descname"><span class="pre">--force</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-timewarp-force" title="Permalink to this definition">#</a></dt>
<dd><p>Bypass confirmation prompt. Use with caution.</p>
</dd></dl>
</section>
<section id="osxphotos-tutorial">
<h3>tutorial<a class="headerlink" href="#osxphotos-tutorial" title="Permalink to this headline">#</a></h3>

View File

@@ -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.1 documentation</title>
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/><title>Index - osxphotos 0.48.4 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.1 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.48.4 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.1 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.48.4 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">
@@ -229,6 +229,39 @@
<li><a href="cli.html#cmdoption-osxphotos-query-add-to-album">osxphotos-query command line option</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-a">osxphotos-timewarp command line option</a>
</li>
</ul></li>
<li>
--added-after
<ul>
<li><a href="cli.html#cmdoption-osxphotos-export-added-after">osxphotos-export command line option</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-query-added-after">osxphotos-query command line option</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-repl-added-after">osxphotos-repl command line option</a>
</li>
</ul></li>
<li>
--added-before
<ul>
<li><a href="cli.html#cmdoption-osxphotos-export-added-before">osxphotos-export command line option</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-query-added-before">osxphotos-query command line option</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-repl-added-before">osxphotos-repl command line option</a>
</li>
</ul></li>
<li>
--added-in-last
<ul>
<li><a href="cli.html#cmdoption-osxphotos-export-added-in-last">osxphotos-export command line option</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-query-added-in-last">osxphotos-query command line option</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-repl-added-in-last">osxphotos-repl command line option</a>
</li>
</ul></li>
<li>
@@ -608,6 +641,13 @@
<li><a href="cli.html#cmdoption-osxphotos-query-folder">osxphotos-query command line option</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-repl-folder">osxphotos-repl command line option</a>
</li>
</ul></li>
<li>
--force
<ul>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-force">osxphotos-timewarp command line option</a>
</li>
</ul></li>
<li>
@@ -1019,6 +1059,8 @@
<li><a href="cli.html#cmdoption-osxphotos-repl-not-cloudasset">osxphotos-repl command line option</a>
</li>
</ul></li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li>
--not-favorite
@@ -1041,8 +1083,6 @@
<li><a href="cli.html#cmdoption-osxphotos-repl-not-hdr">osxphotos-repl command line option</a>
</li>
</ul></li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li>
--not-hidden
@@ -1927,6 +1967,12 @@
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#osxphotos.SearchInfo.activities">activities (osxphotos.SearchInfo property)</a>
</li>
<li><a href="reference.html#osxphotos.QueryOptions.added_after">added_after (osxphotos.QueryOptions attribute)</a>
</li>
<li><a href="reference.html#osxphotos.QueryOptions.added_before">added_before (osxphotos.QueryOptions attribute)</a>
</li>
<li><a href="reference.html#osxphotos.QueryOptions.added_in_last">added_in_last (osxphotos.QueryOptions attribute)</a>
</li>
<li><a href="reference.html#osxphotos.ExifTool.addvalues">addvalues() (osxphotos.ExifTool method)</a>
</li>
@@ -1946,14 +1992,14 @@
</li>
<li><a href="reference.html#osxphotos.AlbumInfo">AlbumInfo (class in osxphotos)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#osxphotos.PhotoInfo.albums">albums (osxphotos.PhotoInfo property)</a>
<ul>
<li><a href="reference.html#osxphotos.PhotosDB.albums">(osxphotos.PhotosDB property)</a>
</li>
</ul></li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#osxphotos.PhotosDB.albums_as_dict">albums_as_dict (osxphotos.PhotosDB property)</a>
</li>
<li><a href="reference.html#osxphotos.PhotosDB.albums_shared">albums_shared (osxphotos.PhotosDB property)</a>
@@ -1969,6 +2015,8 @@
<li><a href="reference.html#osxphotos.ExifTool.asdict">asdict() (osxphotos.ExifTool method)</a>
<ul>
<li><a href="reference.html#osxphotos.MomentInfo.asdict">(osxphotos.MomentInfo method)</a>
</li>
<li><a href="reference.html#osxphotos.PersonInfo.asdict">(osxphotos.PersonInfo method)</a>
</li>
<li><a href="reference.html#osxphotos.PhotoInfo.asdict">(osxphotos.PhotoInfo method)</a>
@@ -2287,6 +2335,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>
@@ -2481,7 +2531,7 @@
<li><a href="reference.html#module-osxphotos">osxphotos</a>
</li>
</ul></li>
<li><a href="reference.html#osxphotos.PhotoInfo.moment">moment (osxphotos.PhotoInfo property)</a>
<li><a href="reference.html#osxphotos.PhotoInfo.moment_info">moment_info (osxphotos.PhotoInfo property)</a>
</li>
<li><a href="reference.html#osxphotos.MomentInfo">MomentInfo (class in osxphotos)</a>
</li>
@@ -2643,6 +2693,12 @@
<li><a href="cli.html#cmdoption-osxphotos-export-add-missing-to-album">--add-missing-to-album</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-export-add-skipped-to-album">--add-skipped-to-album</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-export-added-after">--added-after</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-export-added-before">--added-before</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-export-added-in-last">--added-in-last</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-export-album">--album</a>
</li>
@@ -3006,6 +3062,12 @@
<ul>
<li><a href="cli.html#cmdoption-osxphotos-query-add-to-album">--add-to-album</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-query-added-after">--added-after</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-query-added-before">--added-before</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-query-added-in-last">--added-in-last</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-query-album">--album</a>
</li>
@@ -3172,6 +3234,12 @@
osxphotos-repl command line option
<ul>
<li><a href="cli.html#cmdoption-osxphotos-repl-added-after">--added-after</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-repl-added-before">--added-before</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-repl-added-in-last">--added-in-last</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-repl-album">--album</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-repl-burst">--burst</a>
@@ -3375,6 +3443,8 @@
<li><a href="cli.html#cmdoption-osxphotos-timewarp-D">--date-delta</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-e">--exiftool-path</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-force">--force</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-F">--function</a>
</li>

View File

@@ -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.1 documentation</title>
<title>osxphotos 0.48.4 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.1 documentation</div></a>
<a href="#"><div class="brand">osxphotos 0.48.4 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.1 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.48.4 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">

Binary file not shown.

View File

@@ -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 OSXPhotoss documentation!" href="index.html" />
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
<title>OSXPhotos - osxphotos 0.48.1 documentation</title>
<title>OSXPhotos - osxphotos 0.48.4 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.1 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.48.4 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.1 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.48.4 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

@@ -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.1 documentation</title>
<title>OSXPhotos Python Package Overview - osxphotos 0.48.4 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.1 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.48.4 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.1 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.48.4 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

@@ -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.1 documentation</title>
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/><title>Python Module Index - osxphotos 0.48.4 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.1 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.48.4 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.1 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.48.4 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

View File

@@ -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.1 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.4 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.1 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.48.4 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.1 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.48.4 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

View File

@@ -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.1 documentation</title>
<title>OSXPhotos Template System - osxphotos 0.48.4 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.1 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.48.4 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.1 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.48.4 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">
@@ -509,124 +509,127 @@
<tr class="row-odd"><td><p>{exif.lens_model}</p></td>
<td><p>Lens model from original photos EXIF information as imported by Photos, e.g. iPhone 6s back camera 4.15mm f/2.2</p></td>
</tr>
<tr class="row-even"><td><p>{uuid}</p></td>
<tr class="row-even"><td><p>{moment}</p></td>
<td><p>The moment title of the photo</p></td>
</tr>
<tr class="row-odd"><td><p>{uuid}</p></td>
<td><p>Photos internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, e.g. 128FB4C6-0B16-4E7D-9108-FB2E90DA1546</p></td>
</tr>
<tr class="row-odd"><td><p>{id}</p></td>
<tr class="row-even"><td><p>{id}</p></td>
<td><p>A unique number for the photo based on its primary key in the Photos database. A sequential integer, e.g. 1, 2, 3…etc. Each asset associated with a photo (e.g. an image and Live Photo preview) will share the same id. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use {id:05d} which results in 00001, 00002, 00003…etc.</p></td>
</tr>
<tr class="row-even"><td><p>{album_seq}</p></td>
<tr class="row-odd"><td><p>{album_seq}</p></td>
<td><p>An integer, starting at 0, indicating the photos index (sequence) in the containing album. Only valid when used in a filename template and only when {album} or {folder_album} is used in the directory template. For example directory “{folder_album}” filename “{album<em>seq}</em>{original_name}”’. To start counting at a value other than 0, append append a period and the starting value to the field name. For example, to start counting at 1 instead of 0: {album_seq.1}. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use {album_seq:05d} which results in 00000, 00001, 00002…etc. This may result in incorrect sequences if you have duplicate albums with the same name; see also {folder_album_seq}.</p></td>
</tr>
<tr class="row-odd"><td><p>{folder_album_seq}</p></td>
<tr class="row-even"><td><p>{folder_album_seq}</p></td>
<td><p>An integer, starting at 0, indicating the photos index (sequence) in the containing album and folder path. Only valid when used in a filename template and only when {folder_album} is used in the directory template. For example directory “{folder_album}” filename “{folder_album<em>seq}</em>{original_name}”’. To start counting at a value other than 0, append append a period and the starting value to the field name. For example, to start counting at 1 instead of 0: {folder_album_seq.1} May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use {folder_album_seq:05d} which results in 00000, 00001, 00002…etc. This may result in incorrect sequences if you have duplicate albums with the same name in the same folder; see also {album_seq}.</p></td>
</tr>
<tr class="row-even"><td><p>{comma}</p></td>
<tr class="row-odd"><td><p>{comma}</p></td>
<td><p>A comma: ,</p></td>
</tr>
<tr class="row-odd"><td><p>{semicolon}</p></td>
<tr class="row-even"><td><p>{semicolon}</p></td>
<td><p>A semicolon: ;</p></td>
</tr>
<tr class="row-even"><td><p>{questionmark}</p></td>
<tr class="row-odd"><td><p>{questionmark}</p></td>
<td><p>A question mark: ?</p></td>
</tr>
<tr class="row-odd"><td><p>{pipe}</p></td>
<tr class="row-even"><td><p>{pipe}</p></td>
<td><p>A vertical pipe: |</p></td>
</tr>
<tr class="row-even"><td><p>{openbrace}</p></td>
<tr class="row-odd"><td><p>{openbrace}</p></td>
<td><p>An open brace: {</p></td>
</tr>
<tr class="row-odd"><td><p>{closebrace}</p></td>
<tr class="row-even"><td><p>{closebrace}</p></td>
<td><p>A close brace: }</p></td>
</tr>
<tr class="row-even"><td><p>{openparens}</p></td>
<tr class="row-odd"><td><p>{openparens}</p></td>
<td><p>An open parentheses: (</p></td>
</tr>
<tr class="row-odd"><td><p>{closeparens}</p></td>
<tr class="row-even"><td><p>{closeparens}</p></td>
<td><p>A close parentheses: )</p></td>
</tr>
<tr class="row-even"><td><p>{openbracket}</p></td>
<tr class="row-odd"><td><p>{openbracket}</p></td>
<td><p>An open bracket: [</p></td>
</tr>
<tr class="row-odd"><td><p>{closebracket}</p></td>
<tr class="row-even"><td><p>{closebracket}</p></td>
<td><p>A close bracket: ]</p></td>
</tr>
<tr class="row-even"><td><p>{newline}</p></td>
<tr class="row-odd"><td><p>{newline}</p></td>
<td><p>A newline: n</p></td>
</tr>
<tr class="row-odd"><td><p>{lf}</p></td>
<tr class="row-even"><td><p>{lf}</p></td>
<td><p>A line feed: n, alias for {newline}</p></td>
</tr>
<tr class="row-even"><td><p>{cr}</p></td>
<tr class="row-odd"><td><p>{cr}</p></td>
<td><p>A carriage return: r</p></td>
</tr>
<tr class="row-odd"><td><p>{crlf}</p></td>
<tr class="row-even"><td><p>{crlf}</p></td>
<td><p>a carriage return + line feed: rn</p></td>
</tr>
<tr class="row-even"><td><p>{osxphotos_version}</p></td>
<td><p>The osxphotos version, e.g. 0.48.1</p></td>
<tr class="row-odd"><td><p>{osxphotos_version}</p></td>
<td><p>The osxphotos version, e.g. 0.48.4</p></td>
</tr>
<tr class="row-odd"><td><p>{osxphotos_cmd_line}</p></td>
<tr class="row-even"><td><p>{osxphotos_cmd_line}</p></td>
<td><p>The full command line used to run osxphotos</p></td>
</tr>
<tr class="row-even"><td><p>{album}</p></td>
<tr class="row-odd"><td><p>{album}</p></td>
<td><p>Album(s) photo is contained in</p></td>
</tr>
<tr class="row-odd"><td><p>{folder_album}</p></td>
<tr class="row-even"><td><p>{folder_album}</p></td>
<td><p>Folder path + album photo is contained in. e.g. Folder/Subfolder/Album or just Album if no enclosing folder</p></td>
</tr>
<tr class="row-even"><td><p>{project}</p></td>
<tr class="row-odd"><td><p>{project}</p></td>
<td><p>Project(s) photo is contained in (such as greeting cards, calendars, slideshows)</p></td>
</tr>
<tr class="row-odd"><td><p>{album_project}</p></td>
<tr class="row-even"><td><p>{album_project}</p></td>
<td><p>Album(s) and project(s) photo is contained in; treats projects as regular albums</p></td>
</tr>
<tr class="row-even"><td><p>{folder_album_project}</p></td>
<tr class="row-odd"><td><p>{folder_album_project}</p></td>
<td><p>Folder path + album (includes projects as albums) photo is contained in. e.g. Folder/Subfolder/Album or just Album if no enclosing folder</p></td>
</tr>
<tr class="row-odd"><td><p>{keyword}</p></td>
<tr class="row-even"><td><p>{keyword}</p></td>
<td><p>Keyword(s) assigned to photo</p></td>
</tr>
<tr class="row-even"><td><p>{person}</p></td>
<tr class="row-odd"><td><p>{person}</p></td>
<td><p>Person(s) / face(s) in a photo</p></td>
</tr>
<tr class="row-odd"><td><p>{label}</p></td>
<tr class="row-even"><td><p>{label}</p></td>
<td><p>Image categorization label associated with a photo (Photos 5+ only). Labels are added automatically by Photos using machine learning algorithms to categorize images. These are not the same as {keyword} which refers to the user-defined keywords/tags applied in Photos.</p></td>
</tr>
<tr class="row-even"><td><p>{label_normalized}</p></td>
<tr class="row-odd"><td><p>{label_normalized}</p></td>
<td><p>All lower case version of label (Photos 5+ only)</p></td>
</tr>
<tr class="row-odd"><td><p>{comment}</p></td>
<tr class="row-even"><td><p>{comment}</p></td>
<td><p>Comment(s) on shared Photos; format is Person name: comment text (Photos 5+ only)</p></td>
</tr>
<tr class="row-even"><td><p>{exiftool}</p></td>
<tr class="row-odd"><td><p>{exiftool}</p></td>
<td><p>Format: {exiftool:GROUP:TAGNAME}; use exiftool (https://exiftool.org) to extract metadata, in form GROUP:TAGNAME, from image. E.g. {exiftool:EXIF:Make} to get camera make, or {exiftool:IPTC:Keywords} to extract keywords. See https://exiftool.org/TagNames/ for list of valid tag names. You must specify group (e.g. EXIF, IPTC, etc) as used in <code class="docutils literal notranslate"><span class="pre">exiftool</span> <span class="pre">-G</span></code>. exiftool must be installed in the path to use this template.</p></td>
</tr>
<tr class="row-odd"><td><p>{searchinfo.holiday}</p></td>
<tr class="row-even"><td><p>{searchinfo.holiday}</p></td>
<td><p>Holiday names associated with a photo, e.g. Christmas Day; (Photos 5+ only, applied automatically by Photos image categorization algorithms).</p></td>
</tr>
<tr class="row-even"><td><p>{searchinfo.activity}</p></td>
<tr class="row-odd"><td><p>{searchinfo.activity}</p></td>
<td><p>Activities associated with a photo, e.g. Sporting Event; (Photos 5+ only, applied automatically by Photos image categorization algorithms).</p></td>
</tr>
<tr class="row-odd"><td><p>{searchinfo.venue}</p></td>
<tr class="row-even"><td><p>{searchinfo.venue}</p></td>
<td><p>Venues associated with a photo, e.g. name of restaurant; (Photos 5+ only, applied automatically by Photos image categorization algorithms).</p></td>
</tr>
<tr class="row-even"><td><p>{searchinfo.venue_type}</p></td>
<tr class="row-odd"><td><p>{searchinfo.venue_type}</p></td>
<td><p>Venue types associated with a photo, e.g. Restaurant; (Photos 5+ only, applied automatically by Photos image categorization algorithms).</p></td>
</tr>
<tr class="row-odd"><td><p>{photo}</p></td>
<tr class="row-even"><td><p>{photo}</p></td>
<td><p>Provides direct access to the PhotoInfo object for the photo. Must be used in format {photo.property} where property represents a PhotoInfo property. For example: {photo.favorite} is the same as {favorite} and {photo.place.name} is the same as {place.name}. {photo} provides access to properties that are not available as separate template fields but it assumes some knowledge of the underlying PhotoInfo class. See <a class="reference external" href="https://rhettbull.github.io/osxphotos/">https://rhettbull.github.io/osxphotos/</a> for additional documentation on the PhotoInfo class.</p></td>
</tr>
<tr class="row-even"><td><p>{detected_text}</p></td>
<tr class="row-odd"><td><p>{detected_text}</p></td>
<td><p>List of text strings found in the image after performing text detection. Using {detected_text} will cause osxphotos to perform text detection on your photos using the built-in macOS text detection algorithms which will slow down your export. The results for each photo will be cached in the export database so that future exports with update do not need to reprocess each photo. You may pass a confidence threshold value between 0.0 and 1.0 after a colon as in {detected_text:0.5}; The default confidence threshold is 0.75. {detected_text} works only on macOS Catalina (10.15) or later. Note: this feature is not the same thing as Live Text in macOS Monterey, which osxphotos does not yet support.</p></td>
</tr>
<tr class="row-odd"><td><p>{shell_quote}</p></td>
<tr class="row-even"><td><p>{shell_quote}</p></td>
<td><p>Use in form {shell_quote,TEMPLATE}; quotes the rendered TEMPLATE value(s) for safe usage in the shell, e.g. My file.jpeg =&gt; My file.jpeg; only adds quotes if needed.</p></td>
</tr>
<tr class="row-even"><td><p>{strip}</p></td>
<tr class="row-odd"><td><p>{strip}</p></td>
<td><p>Use in form {strip,TEMPLATE}; strips whitespace from begining and end of rendered TEMPLATE value(s).</p></td>
</tr>
<tr class="row-odd"><td><p>{function}</p></td>
<tr class="row-even"><td><p>{function}</p></td>
<td><p>Execute a python function from an external file and use return value as template substitution. Use in format: {function:file.py::function_name} where file.py is the name of the python file and function_name is the name of the function to call. The function will be passed the PhotoInfo object for the photo. See https://github.com/RhetTbull/osxphotos/blob/master/examples/template_function.py for an example of how to implement a template function.</p></td>
</tr>
</tbody>

View File

@@ -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.1 documentation</title>
<title>OSXPhotos Tutorial - osxphotos 0.48.4 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.1 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.48.4 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.1 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.48.4 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">
@@ -378,6 +378,8 @@
<p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">export</span> <span class="pre">/path/to/export</span> <span class="pre">--portrait</span></code></p>
<p>You can also export photos in a certain date range:</p>
<p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">export</span> <span class="pre">/path/to/export</span> <span class="pre">--from-date</span> <span class="pre">"2020-01-01"</span> <span class="pre">--to-date</span> <span class="pre">"2020-02-28"</span></code></p>
<p>or photos added to the library in the last week:</p>
<p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">export</span> <span class="pre">/path/to/export</span> <span class="pre">--added-in-last</span> <span class="pre">"1</span> <span class="pre">week"</span></code></p>
</section>
<section id="converting-images-to-jpeg-on-export">
<h2>Converting images to JPEG on export<a class="headerlink" href="#converting-images-to-jpeg-on-export" title="Permalink to this headline">#</a></h2>

View File

@@ -281,6 +281,8 @@ Template Substitutions
- Camera model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s'
* - {exif.lens_model}
- Lens model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s back camera 4.15mm f/2.2'
* - {moment}
- The moment title of the photo
* - {uuid}
- Photo's internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'
* - {id}
@@ -318,7 +320,7 @@ Template Substitutions
* - {crlf}
- a carriage return + line feed: '\r\n'
* - {osxphotos_version}
- The osxphotos version, e.g. '0.48.1'
- The osxphotos version, e.g. '0.48.4'
* - {osxphotos_cmd_line}
- The full command line used to run osxphotos
* - {album}

View File

@@ -297,6 +297,10 @@ You can also export photos in a certain date range:
``osxphotos export /path/to/export --from-date "2020-01-01" --to-date "2020-02-28"``
or photos added to the library in the last week:
``osxphotos export /path/to/export --added-in-last "1 week"``
Converting images to JPEG on export
-----------------------------------

View File

@@ -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

View File

@@ -1,3 +1,3 @@
""" version info """
__version__ = "0.48.1"
__version__ = "0.48.4"

View File

@@ -92,7 +92,7 @@ VERSION_CHECK_OPTION = click.option("--no-version-check", required=False, is_fla
DB_OPTION = click.option(
"--db",
required=False,
metavar="<Photos database path>",
metavar="PHOTOS_LIBRARY_PATH",
default=None,
help=(
"Specify Photos database path. "
@@ -380,6 +380,31 @@ def QUERY_OPTIONS(f):
multiple=True,
type=int,
),
o(
"--added-before",
metavar="DATE",
help="Search for items added to the library before a specific date/time, "
"e.g. --added-before e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).",
type=DateTimeISO8601(),
),
o(
"--added-after",
metavar="DATE",
help="Search for items added to the libray after a specific date/time, "
"e.g. --added-after e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).",
type=DateTimeISO8601(),
),
o(
"--added-in-last",
metavar="TIME_DELTA",
help="Search for items added to the library in the last TIME_DELTA, "
"where TIME_DELTA is a string like "
"'12 hrs', '1 day', '1d', '1 week', '2weeks', '1 month', '1 year'. "
"for example, `--added-in-last 7d` and `--added-in-last '1 week'` are equivalent. "
"months are assumed to be 30 days and years are assumed to be 365 days. "
"Common English abbreviations are accepted, e.g. d, day, days or m, min, minutes.",
type=TimeOffset(),
),
o("--has-comment", is_flag=True, help="Search for photos that have comments."),
o("--no-comment", is_flag=True, help="Search for photos with no comments."),
o("--has-likes", is_flag=True, help="Search for photos that have likes."),
@@ -569,4 +594,3 @@ def check_version():
"to suppress this message and prevent osxphotos from checking for latest version.",
err=True,
)

View File

@@ -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. Maybe used with --update to export incrementally.",
type=int,
)
@click.option(
"--dry-run",
is_flag=True,
@@ -505,7 +512,7 @@ from .verbose import get_verbose_console, time_stamp, verbose_print
)
@click.option(
"--report",
metavar="<path to export report>",
metavar="REPORT_FILE",
help="Write a CSV formatted report of all files that were exported.",
type=click.Path(),
)
@@ -600,7 +607,7 @@ from .verbose import get_verbose_console, time_stamp, verbose_print
@click.option(
"--load-config",
required=False,
metavar="<config file path>",
metavar="CONFIG_FILE",
default=None,
help=(
"Load options from file as written with --save-config. "
@@ -615,7 +622,7 @@ from .verbose import get_verbose_console, time_stamp, verbose_print
@click.option(
"--save-config",
required=False,
metavar="<config file path>",
metavar="CONFIG_FILE",
default=None,
help="Save options to file for use with --load-config. File format is TOML. "
"See also --config-only.",
@@ -672,145 +679,149 @@ def export(
cli_obj,
db,
photos_library,
keyword,
person,
album,
folder,
uuid,
name,
uuid_from_file,
title,
no_title,
description,
no_description,
uti,
ignore_case,
edited,
external_edit,
favorite,
not_favorite,
hidden,
not_hidden,
shared,
not_shared,
from_date,
to_date,
from_time,
to_time,
year,
verbose,
timestamp,
no_progress,
missing,
update,
force_update,
ignore_signature,
only_new,
dry_run,
export_as_hardlink,
touch_file,
overwrite,
retry,
export_by_date,
skip_edited,
skip_original_if_edited,
skip_bursts,
skip_live,
skip_raw,
skip_uuid,
skip_uuid_from_file,
person_keyword,
add_exported_to_album,
add_missing_to_album,
add_skipped_to_album,
added_after,
added_before,
added_in_last,
album_keyword,
keyword_template,
replace_keywords,
description_template,
finder_tag_template,
finder_tag_keywords,
xattr_template,
current_name,
convert_to_jpeg,
jpeg_quality,
sidecar,
sidecar_drop_ext,
only_photos,
only_movies,
album,
beta,
burst,
not_burst,
live,
not_live,
download_missing,
cleanup,
config_only,
convert_to_jpeg,
current_name,
deleted_only,
deleted,
description_template,
description,
dest,
exiftool,
exiftool_path,
exiftool_option,
directory,
download_missing,
dry_run,
duplicate,
edited_suffix,
edited,
exif,
exiftool_merge_keywords,
exiftool_merge_persons,
ignore_date_modified,
portrait,
not_portrait,
screenshot,
not_screenshot,
slow_mo,
not_slow_mo,
time_lapse,
not_time_lapse,
hdr,
not_hdr,
selfie,
not_selfie,
panorama,
not_panorama,
has_raw,
directory,
filename_template,
jpeg_ext,
strip,
edited_suffix,
original_suffix,
place,
no_place,
location,
no_location,
has_comment,
no_comment,
has_likes,
no_likes,
label,
deleted,
deleted_only,
use_photos_export,
use_photokit,
report,
cleanup,
add_exported_to_album,
add_skipped_to_album,
add_missing_to_album,
exiftool_option,
exiftool_path,
exiftool,
export_as_hardlink,
export_by_date,
exportdb,
ramdb,
tmpdir,
load_config,
save_config,
config_only,
is_reference,
beta,
external_edit,
favorite,
filename_template,
finder_tag_keywords,
finder_tag_template,
folder,
force_update,
from_date,
from_time,
has_comment,
has_likes,
has_raw,
hdr,
hidden,
ignore_case,
ignore_date_modified,
ignore_signature,
in_album,
not_in_album,
min_size,
is_reference,
jpeg_ext,
jpeg_quality,
keyword_template,
keyword,
label,
limit,
live,
load_config,
location,
max_size,
regex,
selected,
exif,
query_eval,
query_function,
duplicate,
min_size,
missing,
name,
no_comment,
no_description,
no_likes,
no_location,
no_place,
no_progress,
no_title,
not_burst,
not_favorite,
not_hdr,
not_hidden,
not_in_album,
not_live,
not_panorama,
not_portrait,
not_screenshot,
not_selfie,
not_shared,
not_slow_mo,
not_time_lapse,
only_movies,
only_new,
only_photos,
original_suffix,
overwrite,
panorama,
person_keyword,
person,
place,
portrait,
post_command,
post_function,
preview,
preview_suffix,
preview_if_missing,
profile,
preview_suffix,
preview,
profile_sort,
profile,
query_eval,
query_function,
ramdb,
regex,
replace_keywords,
report,
retry,
save_config,
screenshot,
selected,
selfie,
shared,
sidecar_drop_ext,
sidecar,
skip_bursts,
skip_edited,
skip_live,
skip_original_if_edited,
skip_raw,
skip_uuid_from_file,
skip_uuid,
slow_mo,
strip,
theme,
time_lapse,
timestamp,
title,
tmpdir,
to_date,
to_time,
touch_file,
update,
use_photokit,
use_photos_export,
uti,
uuid_from_file,
uuid,
verbose,
xattr_template,
year,
debug, # debug, watch, breakpoint handled in cli/__init__.py
watch,
breakpoint,
@@ -886,6 +897,9 @@ def export(
# re-set the local vars to the corresponding config value
# this isn't elegant but avoids having to rewrite this function to use cfg.varname for every parameter
added_after = cfg.added_after
added_before = cfg.added_before
added_in_last = cfg.added_in_last
add_exported_to_album = cfg.add_exported_to_album
add_missing_to_album = cfg.add_missing_to_album
add_skipped_to_album = cfg.add_skipped_to_album
@@ -939,6 +953,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
@@ -1038,41 +1053,41 @@ def export(
# validate options
exclusive_options = [
("favorite", "not_favorite"),
("hidden", "not_hidden"),
("title", "no_title"),
("description", "no_description"),
("only_photos", "only_movies"),
("burst", "not_burst"),
("live", "not_live"),
("portrait", "not_portrait"),
("screenshot", "not_screenshot"),
("slow_mo", "not_slow_mo"),
("time_lapse", "not_time_lapse"),
("hdr", "not_hdr"),
("selfie", "not_selfie"),
("panorama", "not_panorama"),
("export_by_date", "directory"),
("export_as_hardlink", "exiftool"),
("place", "no_place"),
("deleted", "deleted_only"),
("skip_edited", "skip_original_if_edited"),
("description", "no_description"),
("export_as_hardlink", "convert_to_jpeg"),
("export_as_hardlink", "download_missing"),
("shared", "not_shared"),
("export_as_hardlink", "exiftool"),
("export_by_date", "directory"),
("favorite", "not_favorite"),
("has_comment", "no_comment"),
("has_likes", "no_likes"),
("hdr", "not_hdr"),
("hidden", "not_hidden"),
("in_album", "not_in_album"),
("live", "not_live"),
("location", "no_location"),
("only_photos", "only_movies"),
("panorama", "not_panorama"),
("place", "no_place"),
("portrait", "not_portrait"),
("screenshot", "not_screenshot"),
("selfie", "not_selfie"),
("shared", "not_shared"),
("skip_edited", "skip_original_if_edited"),
("slow_mo", "not_slow_mo"),
("time_lapse", "not_time_lapse"),
("title", "no_title"),
]
dependent_options = [
("missing", ("download_missing", "use_photos_export")),
("jpeg_quality", ("convert_to_jpeg")),
("ignore_signature", ("update", "force_update")),
("only_new", ("update", "force_update")),
("exiftool_option", ("exiftool")),
("exiftool_merge_keywords", ("exiftool", "sidecar")),
("exiftool_merge_persons", ("exiftool", "sidecar")),
("exiftool_option", ("exiftool")),
("ignore_signature", ("update", "force_update")),
("jpeg_quality", ("convert_to_jpeg")),
("missing", ("download_missing", "use_photos_export")),
("only_new", ("update", "force_update")),
]
try:
cfg.validate(exclusive=exclusive_options, dependent=dependent_options, cli=True)
@@ -1267,83 +1282,86 @@ def export(
photosdb._beta = beta
query_options = QueryOptions(
keyword=keyword,
person=person,
added_after=added_after,
added_before=added_before,
added_in_last=added_in_last,
album=album,
folder=folder,
uuid=uuid,
title=title,
no_title=no_title,
burst_photos=export_bursts,
burst=burst,
cloudasset=False,
deleted_only=deleted_only,
deleted=deleted,
description=description,
no_description=no_description,
ignore_case=ignore_case,
duplicate=duplicate,
edited=edited,
exif=exif,
external_edit=external_edit,
favorite=favorite,
not_favorite=not_favorite,
hidden=hidden,
not_hidden=not_hidden,
missing=missing,
not_missing=None,
shared=shared,
not_shared=not_shared,
photos=photos,
movies=movies,
uti=uti,
burst=burst,
not_burst=not_burst,
live=live,
not_live=not_live,
cloudasset=False,
not_cloudasset=False,
incloud=False,
not_incloud=False,
folder=folder,
from_date=from_date,
to_date=to_date,
from_time=from_time,
to_time=to_time,
year=year,
portrait=portrait,
not_portrait=not_portrait,
screenshot=screenshot,
not_screenshot=not_screenshot,
slow_mo=slow_mo,
not_slow_mo=not_slow_mo,
time_lapse=time_lapse,
not_time_lapse=not_time_lapse,
hdr=hdr,
not_hdr=not_hdr,
selfie=selfie,
not_selfie=not_selfie,
panorama=panorama,
not_panorama=not_panorama,
has_raw=has_raw,
place=place,
no_place=no_place,
location=location,
no_location=no_location,
label=label,
deleted=deleted,
deleted_only=deleted_only,
function=query_function,
has_comment=has_comment,
no_comment=no_comment,
has_likes=has_likes,
no_likes=no_likes,
is_reference=is_reference,
has_raw=has_raw,
hdr=hdr,
hidden=hidden,
ignore_case=ignore_case,
in_album=in_album,
not_in_album=not_in_album,
burst_photos=export_bursts,
incloud=False,
is_reference=is_reference,
keyword=keyword,
label=label,
live=live,
location=location,
max_size=max_size,
min_size=min_size,
# skip missing bursts if using --download-missing by itself as AppleScript otherwise causes errors
missing_bursts=(download_missing and use_photokit) or not download_missing,
missing=missing,
movies=movies,
name=name,
min_size=min_size,
max_size=max_size,
regex=regex,
selected=selected,
exif=exif,
no_comment=no_comment,
no_description=no_description,
no_likes=no_likes,
no_location=no_location,
no_place=no_place,
no_title=no_title,
not_burst=not_burst,
not_cloudasset=False,
not_favorite=not_favorite,
not_hdr=not_hdr,
not_hidden=not_hidden,
not_in_album=not_in_album,
not_incloud=False,
not_live=not_live,
not_missing=None,
not_panorama=not_panorama,
not_portrait=not_portrait,
not_screenshot=not_screenshot,
not_selfie=not_selfie,
not_shared=not_shared,
not_slow_mo=not_slow_mo,
not_time_lapse=not_time_lapse,
panorama=panorama,
person=person,
photos=photos,
place=place,
portrait=portrait,
query_eval=query_eval,
function=query_function,
duplicate=duplicate,
regex=regex,
screenshot=screenshot,
selected=selected,
selfie=selfie,
shared=shared,
slow_mo=slow_mo,
time_lapse=time_lapse,
title=title,
to_date=to_date,
to_time=to_time,
uti=uti,
uuid=uuid,
year=year,
)
try:
@@ -1374,8 +1392,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}[/]..."
)
@@ -1403,9 +1420,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
@@ -1570,7 +1589,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}, "
@@ -1588,6 +1617,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)}")

View File

@@ -2,10 +2,11 @@
import datetime
import os
import pathlib
import re
import bitmath
import click
import pytimeparse
import pytimeparse2
from osxphotos.export_db_utils import export_db_get_version
from osxphotos.photoinfo import PhotoInfoNone
@@ -159,19 +160,31 @@ class DateOffset(click.ParamType):
name = "DATEOFFSET"
def convert(self, value, param, ctx):
offset = pytimeparse.parse(value)
# if it's a single number treat it as days
# but pytimeparse2 treats is as seconds so need to verify it's just a number and if so,
# convert it to seconds
value = value.strip()
if re.match(r"^[+-]?\s*?\d+$", value):
# just a number
# strip any whitespace, e.g. for "+ 1" or "- 1"
value = "".join(value.split())
try:
return datetime.timedelta(days=int(value))
except ValueError:
self.fail(
f"Invalid date offset format: {value}. "
"Valid format for date/time offset: '±D days', '±W weeks', '±M months', '±D' where D is days "
)
offset = pytimeparse2.parse(value)
if offset is not None:
offset = offset / 86400
return datetime.timedelta(days=offset)
# could be in format "-1" (negative offset) or "+1" (positive offset)
try:
return datetime.timedelta(days=int(value))
except ValueError:
self.fail(
f"Invalid date offset format: {value}. "
"Valid format for date/time offset: '±D days', '±W weeks', '±D' where D is days "
)
self.fail(
f"Invalid date offset format: {value}. "
"Valid format for date/time offset: '±D days', '±W weeks', '±M months', '±D' where D is days "
)
class TimeOffset(click.ParamType):
@@ -180,18 +193,14 @@ class TimeOffset(click.ParamType):
name = "TIMEOFFSET"
def convert(self, value, param, ctx):
offset = pytimeparse.parse(value)
offset = pytimeparse2.parse(value)
if offset is not None:
return datetime.timedelta(seconds=offset)
# could be in format "-18000" (negative offset) or "+18000" (positive offset)
try:
return datetime.timedelta(seconds=int(value))
except ValueError:
self.fail(
f"Invalid time offset format: {value}. "
"Valid format for date/time offset: '±HH:MM:SS', '±H hours' (or hr), '±M minutes' (or min), '±S seconds' (or sec), '±S' (where S is seconds)"
)
self.fail(
f"Invalid time offset format: {value}. "
"Valid format for date/time offset: '±HH:MM:SS', '±H hours' (or hr), '±M minutes' (or min), '±S seconds' (or sec), '±S' (where S is seconds)"
)
class UTCOffset(click.ParamType):

View File

@@ -73,83 +73,86 @@ def query(
cli_obj,
db,
photos_library,
keyword,
person,
add_to_album,
added_after,
added_before,
added_in_last,
album,
folder,
name,
uuid,
uuid_from_file,
title,
no_title,
burst,
cloudasset,
deleted_only,
deleted,
description,
no_description,
ignore_case,
json_,
duplicate,
edited,
exif,
external_edit,
favorite,
not_favorite,
folder,
from_date,
from_time,
has_comment,
has_likes,
has_raw,
hdr,
hidden,
not_hidden,
ignore_case,
in_album,
incloud,
is_reference,
json_,
keyword,
label,
live,
location,
max_size,
min_size,
missing,
name,
no_comment,
no_description,
no_likes,
no_location,
no_place,
no_title,
not_burst,
not_cloudasset,
not_favorite,
not_hdr,
not_hidden,
not_in_album,
not_incloud,
not_live,
not_missing,
shared,
not_panorama,
not_portrait,
not_screenshot,
not_selfie,
not_shared,
not_slow_mo,
not_time_lapse,
only_movies,
only_photos,
uti,
burst,
not_burst,
live,
not_live,
cloudasset,
not_cloudasset,
incloud,
not_incloud,
from_date,
to_date,
from_time,
to_time,
year,
portrait,
not_portrait,
screenshot,
not_screenshot,
slow_mo,
not_slow_mo,
time_lapse,
not_time_lapse,
hdr,
not_hdr,
selfie,
not_selfie,
panorama,
not_panorama,
has_raw,
person,
place,
no_place,
location,
no_location,
label,
deleted,
deleted_only,
has_comment,
no_comment,
has_likes,
no_likes,
is_reference,
in_album,
not_in_album,
duplicate,
min_size,
max_size,
regex,
selected,
exif,
portrait,
query_eval,
query_function,
add_to_album,
regex,
screenshot,
selected,
selfie,
shared,
slow_mo,
time_lapse,
title,
to_date,
to_time,
uti,
uuid_from_file,
uuid,
year,
debug, # handled in cli/__init__.py
):
"""Query the Photos database using 1 or more search options;
@@ -160,58 +163,61 @@ def query(
# if no query terms, show help and return
# sanity check input args
nonexclusive = [
keyword,
person,
added_after,
added_before,
added_in_last,
album,
folder,
name,
uuid,
uuid_from_file,
duplicate,
edited,
exif,
external_edit,
uti,
has_raw,
folder,
from_date,
to_date,
from_time,
to_time,
year,
label,
has_raw,
is_reference,
keyword,
label,
max_size,
min_size,
name,
person,
query_eval,
query_function,
min_size,
max_size,
regex,
selected,
exif,
duplicate,
to_date,
to_time,
uti,
uuid_from_file,
uuid,
year,
]
exclusive = [
(favorite, not_favorite),
(hidden, not_hidden),
(missing, not_missing),
(any(title), no_title),
(any(description), no_description),
(only_photos, only_movies),
(burst, not_burst),
(live, not_live),
(cloudasset, not_cloudasset),
(incloud, not_incloud),
(portrait, not_portrait),
(screenshot, not_screenshot),
(slow_mo, not_slow_mo),
(time_lapse, not_time_lapse),
(hdr, not_hdr),
(selfie, not_selfie),
(panorama, not_panorama),
(any(place), no_place),
(any(title), no_title),
(burst, not_burst),
(cloudasset, not_cloudasset),
(deleted, deleted_only),
(shared, not_shared),
(favorite, not_favorite),
(has_comment, no_comment),
(has_likes, no_likes),
(hdr, not_hdr),
(hidden, not_hidden),
(in_album, not_in_album),
(incloud, not_incloud),
(live, not_live),
(location, no_location),
(missing, not_missing),
(only_photos, only_movies),
(panorama, not_panorama),
(portrait, not_portrait),
(screenshot, not_screenshot),
(selfie, not_selfie),
(shared, not_shared),
(slow_mo, not_slow_mo),
(time_lapse, not_time_lapse),
]
# print help if no non-exclusive term or a double exclusive term is given
if any(all(bb) for bb in exclusive) or not any(
@@ -247,80 +253,83 @@ def query(
photosdb = osxphotos.PhotosDB(dbfile=db)
query_options = QueryOptions(
keyword=keyword,
person=person,
added_after=added_after,
added_before=added_before,
added_in_last=added_in_last,
album=album,
folder=folder,
uuid=uuid,
title=title,
no_title=no_title,
burst=burst,
cloudasset=cloudasset,
deleted_only=deleted_only,
deleted=deleted,
description=description,
no_description=no_description,
ignore_case=ignore_case,
duplicate=duplicate,
edited=edited,
exif=exif,
external_edit=external_edit,
favorite=favorite,
not_favorite=not_favorite,
hidden=hidden,
not_hidden=not_hidden,
missing=missing,
not_missing=not_missing,
shared=shared,
not_shared=not_shared,
photos=photos,
movies=movies,
uti=uti,
burst=burst,
not_burst=not_burst,
live=live,
not_live=not_live,
cloudasset=cloudasset,
not_cloudasset=not_cloudasset,
incloud=incloud,
not_incloud=not_incloud,
folder=folder,
from_date=from_date,
to_date=to_date,
from_time=from_time,
to_time=to_time,
year=year,
portrait=portrait,
not_portrait=not_portrait,
screenshot=screenshot,
not_screenshot=not_screenshot,
slow_mo=slow_mo,
not_slow_mo=not_slow_mo,
time_lapse=time_lapse,
not_time_lapse=not_time_lapse,
hdr=hdr,
not_hdr=not_hdr,
selfie=selfie,
not_selfie=not_selfie,
panorama=panorama,
not_panorama=not_panorama,
has_raw=has_raw,
place=place,
no_place=no_place,
location=location,
no_location=no_location,
label=label,
deleted=deleted,
deleted_only=deleted_only,
has_comment=has_comment,
no_comment=no_comment,
has_likes=has_likes,
no_likes=no_likes,
is_reference=is_reference,
in_album=in_album,
not_in_album=not_in_album,
name=name,
min_size=min_size,
max_size=max_size,
query_eval=query_eval,
function=query_function,
has_comment=has_comment,
has_likes=has_likes,
has_raw=has_raw,
hdr=hdr,
hidden=hidden,
ignore_case=ignore_case,
in_album=in_album,
incloud=incloud,
is_reference=is_reference,
keyword=keyword,
label=label,
live=live,
location=location,
max_size=max_size,
min_size=min_size,
missing=missing,
movies=movies,
name=name,
no_comment=no_comment,
no_description=no_description,
no_likes=no_likes,
no_location=no_location,
no_place=no_place,
no_title=no_title,
not_burst=not_burst,
not_cloudasset=not_cloudasset,
not_favorite=not_favorite,
not_hdr=not_hdr,
not_hidden=not_hidden,
not_in_album=not_in_album,
not_incloud=not_incloud,
not_live=not_live,
not_missing=not_missing,
not_panorama=not_panorama,
not_portrait=not_portrait,
not_screenshot=not_screenshot,
not_selfie=not_selfie,
not_shared=not_shared,
not_slow_mo=not_slow_mo,
not_time_lapse=not_time_lapse,
panorama=panorama,
person=person,
photos=photos,
place=place,
portrait=portrait,
query_eval=query_eval,
regex=regex,
screenshot=screenshot,
selected=selected,
exif=exif,
duplicate=duplicate,
selfie=selfie,
shared=shared,
slow_mo=slow_mo,
time_lapse=time_lapse,
title=title,
to_date=to_date,
to_time=to_time,
uti=uti,
uuid=uuid,
year=year,
)
try:

View File

@@ -241,55 +241,58 @@ def _query_options_from_kwargs(**kwargs) -> QueryOptions:
"""Validate query options and create a QueryOptions instance"""
# sanity check input args
nonexclusive = [
"keyword",
"person",
"added_after",
"added_before",
"added_in_last",
"album",
"folder",
"name",
"uuid",
"uuid_from_file",
"duplicate",
"edited",
"exif",
"external_edit",
"uti",
"has_raw",
"folder",
"from_date",
"to_date",
"from_time",
"to_time",
"year",
"label",
"has_raw",
"is_reference",
"keyword",
"label",
"max_size",
"min_size",
"name",
"person",
"query_eval",
"query_function",
"min_size",
"max_size",
"regex",
"selected",
"exif",
"duplicate",
"to_date",
"to_time",
"uti",
"uuid_from_file",
"uuid",
"year",
]
exclusive = [
("favorite", "not_favorite"),
("hidden", "not_hidden"),
("missing", "not_missing"),
("only_photos", "only_movies"),
("burst", "not_burst"),
("live", "not_live"),
("cloudasset", "not_cloudasset"),
("incloud", "not_incloud"),
("portrait", "not_portrait"),
("screenshot", "not_screenshot"),
("slow_mo", "not_slow_mo"),
("time_lapse", "not_time_lapse"),
("hdr", "not_hdr"),
("selfie", "not_selfie"),
("panorama", "not_panorama"),
("deleted", "deleted_only"),
("shared", "not_shared"),
("favorite", "not_favorite"),
("has_comment", "no_comment"),
("has_likes", "no_likes"),
("hdr", "not_hdr"),
("hidden", "not_hidden"),
("in_album", "not_in_album"),
("incloud", "not_incloud"),
("live", "not_live"),
("location", "no_location"),
("missing", "not_missing"),
("only_photos", "only_movies"),
("panorama", "not_panorama"),
("portrait", "not_portrait"),
("screenshot", "not_screenshot"),
("selfie", "not_selfie"),
("shared", "not_shared"),
("slow_mo", "not_slow_mo"),
("time_lapse", "not_time_lapse"),
]
# print help if no non-exclusive term or a double exclusive term is given
# TODO: add option to validate requiring at least one query arg

View File

@@ -218,6 +218,11 @@ For this to work, you'll need to install the third-party exiftool (https://exift
`osxphotos timewarp --compare-exif`
**Read the date/time/timezone from the photos' original EXIF metadata to update the photos' date/time/timezone;
if the EXIF data is missing, use the file modification date/time; show verbose output**
`osxphotos timewarp --pull-exif --use-file-time --verbose`
"""
),
width=formatter.width,
@@ -394,6 +399,11 @@ For this to work, you'll need to install the third-party exiftool (https://exift
is_flag=True,
help="Plain text mode. Do not use rich output.",
)
@click.option(
"--force",
is_flag=True,
help="Bypass confirmation prompt. Use with caution.",
)
def timewarp(
date,
date_delta,
@@ -416,6 +426,7 @@ def timewarp(
output_file,
terminal_width,
timestamp,
force,
):
"""Adjust date/time/timezone of photos in Apple Photos.
@@ -458,6 +469,8 @@ def timewarp(
if add_to_album and not compare_exif:
raise click.UsageError("--add-to-album must be used with --compare-exif.")
# configure colored rich output
# TODO: this is all a little hacky, find a better way to do this
color_theme = get_theme(theme)
verbose_ = verbose_print(
verbose,
@@ -468,7 +481,6 @@ def timewarp(
file=output_file,
)
# set console for rich_echo to be same as for verbose_
# TODO: this is a hack, find a better way to do this
terminal_width = terminal_width or (1000 if output_file else None)
if output_file:
set_rich_console(Console(file=output_file, width=terminal_width))
@@ -509,6 +521,35 @@ def timewarp(
)
sys.exit(1)
# confirm with user before proceeding
if (
any(
[
date,
date_delta,
time,
time_delta,
timezone,
push_exif,
pull_exif,
function,
]
)
and not force
):
click.confirm(
rich_text(
f":warning-emoji: About to process [num]{len(photos)}[/] {pluralize(len(photos), 'photo', 'photos')} with timewarp. "
"This will directly modify your Photos library database using undocumented features. "
"While this functionality has been well tested, it is possible this may "
"corrupt, damage, or destroy your Photos library. [bold]Use at your own caution. No warranty is implied or provided.[/] "
"It is strongly recommended you make a backup of your Photos library before using the timewarp command "
"(for example, using Time Machine).\n\n"
"Proceed with timewarp?"
),
abort=True,
)
update_photo_date_time_ = partial(
update_photo_date_time,
date=date,
@@ -652,6 +693,3 @@ def timewarp(
progress.advance(task)
rich_echo("Done.")
# if output_file:
# output_file.close()

Binary file not shown.

View File

@@ -68,3 +68,19 @@ class MomentInfo:
self._photos = self._db.photos_by_uuid(photo_uuids)
return self._photos
def asdict(self):
"""Returns all moment info as dictionary"""
return {
"pk": self.pk,
"location": self.location,
"title": self.title,
"subtitle": self.subtitle,
"start_date": self.start_date.isoformat() if self.start_date else None,
"end_date": self.end_date.isoformat() if self.end_date else None,
"date": self.date.isoformat() if self.date else None,
"modification_date": self.modification_date.isoformat()
if self.modification_date
else None,
"photos": self.photos,
}

View File

@@ -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.

View File

@@ -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"]
@@ -479,7 +480,7 @@ class PhotoInfo:
return self._faceinfo
@property
def moment(self):
def moment_info(self):
"""Moment photo belongs to"""
try:
return self._moment
@@ -1356,6 +1357,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)

View File

@@ -14,8 +14,8 @@ import tempfile
from collections import OrderedDict
from collections.abc import Iterable
from datetime import datetime, timedelta, timezone
from pprint import pformat
from typing import List
from unicodedata import normalize
import bitmath
import photoscript
@@ -2566,8 +2566,16 @@ class PhotosDB:
moment_info[date_name] = moment_date.astimezone(tz=tz)
# process title/subtitle
moment_info["title"] = moment_info["title"] or ""
moment_info["subtitle"] = moment_info["subtitle"] or ""
# use unicodedata.normalize with KFKC instead of normalize_unicode as is done elsewhere
# to replace non-breaking whitespace chars with spaces as Photos uses \xa0 as space in Moment titles, subtitles
moment_info["title"] = (
normalize("NFKC", moment_info["title"]) if moment_info["title"] else ""
)
moment_info["subtitle"] = (
normalize("NFKC", moment_info["subtitle"])
if moment_info["subtitle"]
else ""
)
self._db_moment_pk[moment_info["pk"]] = moment_info
@@ -3438,6 +3446,23 @@ class PhotosDB:
matching_photos.append(p)
photos = matching_photos
if options.added_after:
added_after = options.added_after
if not datetime_has_tz(added_after):
added_after = datetime_naive_to_local(added_after)
photos = [p for p in photos if p.date_added and p.date_added > added_after]
if options.added_before:
added_before = options.added_before
if not datetime_has_tz(added_before):
added_before = datetime_naive_to_local(added_before)
photos = [p for p in photos if p.date_added and p.date_added < added_before]
if options.added_in_last:
added_after = datetime.now() - options.added_in_last
added_after = datetime_naive_to_local(added_after)
photos = [p for p in photos if p.date_added and p.date_added > added_after]
if options.function:
for function in options.function:
photos = function[0](photos)

View File

@@ -138,6 +138,7 @@ TEMPLATE_SUBSTITUTIONS = {
"{exif.camera_make}": "Camera make from original photo's EXIF information as imported by Photos, e.g. 'Apple'",
"{exif.camera_model}": "Camera model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s'",
"{exif.lens_model}": "Lens model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s back camera 4.15mm f/2.2'",
"{moment}": "The moment title of the photo",
"{uuid}": "Photo's internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'",
"{id}": "A unique number for the photo based on its primary key in the Photos database. "
+ "A sequential integer, e.g. 1, 2, 3...etc. Each asset associated with a photo (e.g. an image and Live Photo preview) will share the same id. "
@@ -974,6 +975,8 @@ class PhotoTemplate:
value = self.photo.exif_info.camera_model if self.photo.exif_info else None
elif field == "exif.lens_model":
value = self.photo.exif_info.lens_model if self.photo.exif_info else None
elif field == "moment":
value = self.photo.moment_info.title if self.photo.moment_info else None
elif field == "uuid":
value = self.photo.uuid
elif field == "id":

View File

@@ -15,158 +15,163 @@ class QueryOptions:
"""QueryOptions class for PhotosDB.query
Attributes:
keyword: list of keywords to search for
person: list of person names to search for
added_after: search for photos added after a given date
added_before: search for photos added before a given date
added_in_last: search for photos added in last X datetime.timedelta
album: list of album names to search for
folder: list of folder names to search for
uuid: list of uuids to search for
title: list of titles to search for
no_title: search for photos with no title
burst_photos: search for burst photos
burst: search for burst photos
cloudasset: search for photos that are managed by iCloud
deleted_only: search only for deleted photos
deleted: also include deleted photos
description: list of descriptions to search for
no_description: search for photos with no description
ignore_case: ignore case when searching
duplicate: search for duplicate photos
edited: search for edited photos
exif: search for photos with EXIF tags that matches the given data
external_edit: search for photos edited in external apps
favorite: search for favorite photos
not_favorite: search for non-favorite photos
hidden: search for hidden photos
not_hidden: search for non-hidden photos
missing: search for missing photos
not_missing: search for non-missing photos
shared: search for shared photos
not_shared: search for non-shared photos
photos: search for photos
movies: search for movies
uti: list of UTIs to search for
burst: search for burst photos
not_burst: search for non-burst photos
live: search for live photos
not_live: search for non-live photos
cloudasset: search for photos that are managed by iCloud
not_cloudasset: search for photos that are not managed by iCloud
incloud: search for cloud assets that are synched to iCloud
not_incloud: search for cloud asset photos that are not yet synched to iCloud
folder: list of folder names to search for
from_date: search for photos taken on or after this date
to_date: search for photos taken on or before this date
portrait: search for portrait photos
not_portrait: search for non-portrait photos
screenshot: search for screenshot photos
not_screenshot: search for non-screenshot photos
slow_mo: search for slow-mo photos
not_slow_mo: search for non-slow-mo photos
time_lapse: search for time-lapse photos
not_time_lapse: search for non-time-lapse photos
hdr: search for HDR photos
not_hdr: search for non-HDR photos
selfie: search for selfie photos
not_selfie: search for non-selfie photos
panorama: search for panorama photos
not_panorama: search for non-panorama photos
has_raw: search for photos with associated raw files
place: list of place names to search for
no_place: search for photos with no place
label: list of labels to search for
deleted: also include deleted photos
deleted_only: search only for deleted photos
has_comment: search for photos with comments
no_comment: search for photos with no comments
has_likes: search for shared photos with likes
no_likes: search for shared photos with no likes
is_reference: search for photos stored by reference (that is, they are not managed by Photos)
in_album: search for photos in an album
not_in_album: search for photos not in an album
burst_photos: search for burst photos
missing_bursts: for burst photos, also include burst photos that are missing
name: list of names to search for
min_size: minimum size of photos to search for
max_size: maximum size of photos to search for
regex: list of regular expressions to search for
query_eval: list of query expressions to evaluate
duplicate: search for duplicate photos
location: search for photos with a location
no_location: search for photos with no location
function: list of query functions to evaluate
has_comment: search for photos with comments
has_likes: search for shared photos with likes
has_raw: search for photos with associated raw files
hdr: search for HDR photos
hidden: search for hidden photos
ignore_case: ignore case when searching
in_album: search for photos in an album
incloud: search for cloud assets that are synched to iCloud
is_reference: search for photos stored by reference (that is, they are not managed by Photos)
keyword: list of keywords to search for
label: list of labels to search for
live: search for live photos
location: search for photos with a location
max_size: maximum size of photos to search for
min_size: minimum size of photos to search for
missing_bursts: for burst photos, also include burst photos that are missing
missing: search for missing photos
movies: search for movies
name: list of names to search for
no_comment: search for photos with no comments
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_place: search for photos with no place
no_title: search for photos with no title
not_burst: search for non-burst photos
not_cloudasset: search for photos that are not managed by iCloud
not_favorite: search for non-favorite photos
not_hdr: search for non-HDR photos
not_hidden: search for non-hidden photos
not_in_album: search for photos not in an album
not_incloud: search for cloud asset photos that are not yet synched to iCloud
not_live: search for non-live photos
not_missing: search for non-missing photos
not_panorama: search for non-panorama photos
not_portrait: search for non-portrait photos
not_screenshot: search for non-screenshot photos
not_selfie: search for non-selfie photos
not_shared: search for non-shared photos
not_slow_mo: search for non-slow-mo photos
not_time_lapse: search for non-time-lapse photos
panorama: search for panorama photos
person: list of person names to search for
photos: search for photos
place: list of place names to search for
portrait: search for portrait photos
query_eval: list of query expressions to evaluate
regex: list of regular expressions to search for
screenshot: search for screenshot photos
selected: search for selected photos
exif: search for photos with EXIF tags that matches the given data
selfie: search for selfie photos
shared: search for shared photos
slow_mo: search for slow-mo photos
time_lapse: search for time-lapse photos
title: list of titles to search for
to_date: search for photos taken on or before this date
uti: list of UTIs to search for
uuid: list of uuids to search for
year: search for photos taken in a given year
"""
keyword: Optional[Iterable[str]] = None
person: Optional[Iterable[str]] = None
added_after: Optional[datetime.datetime] = None
added_before: Optional[datetime.datetime] = None
added_in_last: Optional[datetime.timedelta] = None
album: Optional[Iterable[str]] = None
folder: Optional[Iterable[str]] = None
uuid: Optional[Iterable[str]] = None
title: Optional[Iterable[str]] = None
no_title: Optional[bool] = None
burst_photos: Optional[bool] = None
burst: Optional[bool] = None
cloudasset: Optional[bool] = None
deleted_only: Optional[bool] = None
deleted: Optional[bool] = None
description: Optional[Iterable[str]] = None
no_description: Optional[bool] = None
ignore_case: Optional[bool] = None
duplicate: Optional[bool] = None
edited: Optional[bool] = None
exif: Optional[Iterable[Tuple[str, str]]] = None
external_edit: Optional[bool] = None
favorite: Optional[bool] = None
not_favorite: Optional[bool] = None
hidden: Optional[bool] = None
not_hidden: Optional[bool] = None
missing: Optional[bool] = None
not_missing: Optional[bool] = None
shared: Optional[bool] = None
not_shared: Optional[bool] = None
photos: Optional[bool] = True
movies: Optional[bool] = True
uti: Optional[Iterable[str]] = None
burst: Optional[bool] = None
not_burst: Optional[bool] = None
live: Optional[bool] = None
not_live: Optional[bool] = None
cloudasset: Optional[bool] = None
not_cloudasset: Optional[bool] = None
incloud: Optional[bool] = None
not_incloud: Optional[bool] = None
folder: Optional[Iterable[str]] = None
from_date: Optional[datetime.datetime] = None
to_date: Optional[datetime.datetime] = None
from_time: Optional[datetime.time] = None
to_time: Optional[datetime.time] = None
portrait: Optional[bool] = None
not_portrait: Optional[bool] = None
screenshot: Optional[bool] = None
not_screenshot: Optional[bool] = None
slow_mo: Optional[bool] = None
not_slow_mo: Optional[bool] = None
time_lapse: Optional[bool] = None
not_time_lapse: Optional[bool] = None
hdr: Optional[bool] = None
not_hdr: Optional[bool] = None
selfie: Optional[bool] = None
not_selfie: Optional[bool] = None
panorama: Optional[bool] = None
not_panorama: Optional[bool] = None
has_raw: Optional[bool] = None
place: Optional[Iterable[str]] = None
no_place: Optional[bool] = None
label: Optional[Iterable[str]] = None
deleted: Optional[bool] = None
deleted_only: Optional[bool] = None
has_comment: Optional[bool] = None
no_comment: Optional[bool] = None
has_likes: Optional[bool] = None
no_likes: Optional[bool] = None
is_reference: Optional[bool] = None
in_album: Optional[bool] = None
not_in_album: Optional[bool] = None
burst_photos: Optional[bool] = None
missing_bursts: Optional[bool] = None
name: Optional[Iterable[str]] = None
min_size: Optional[bitmath.Byte] = None
max_size: Optional[bitmath.Byte] = None
regex: Optional[Iterable[Tuple[str, str]]] = None
query_eval: Optional[Iterable[str]] = None
duplicate: Optional[bool] = None
location: Optional[bool] = None
no_location: Optional[bool] = None
function: Optional[List[Tuple[callable, str]]] = None
has_comment: Optional[bool] = None
has_likes: Optional[bool] = None
has_raw: Optional[bool] = None
hdr: Optional[bool] = None
hidden: Optional[bool] = None
ignore_case: Optional[bool] = None
in_album: Optional[bool] = None
incloud: Optional[bool] = None
is_reference: Optional[bool] = None
keyword: Optional[Iterable[str]] = None
label: Optional[Iterable[str]] = None
live: Optional[bool] = None
location: Optional[bool] = None
max_size: Optional[bitmath.Byte] = None
min_size: Optional[bitmath.Byte] = None
missing_bursts: Optional[bool] = None
missing: Optional[bool] = None
movies: Optional[bool] = True
name: Optional[Iterable[str]] = None
no_comment: Optional[bool] = None
no_description: Optional[bool] = None
no_likes: Optional[bool] = None
no_location: Optional[bool] = None
no_place: Optional[bool] = None
no_title: Optional[bool] = None
not_burst: Optional[bool] = None
not_cloudasset: Optional[bool] = None
not_favorite: Optional[bool] = None
not_hdr: Optional[bool] = None
not_hidden: Optional[bool] = None
not_in_album: Optional[bool] = None
not_incloud: Optional[bool] = None
not_live: Optional[bool] = None
not_missing: Optional[bool] = None
not_panorama: Optional[bool] = None
not_portrait: Optional[bool] = None
not_screenshot: Optional[bool] = None
not_selfie: Optional[bool] = None
not_shared: Optional[bool] = None
not_slow_mo: Optional[bool] = None
not_time_lapse: Optional[bool] = None
panorama: Optional[bool] = None
person: Optional[Iterable[str]] = None
photos: Optional[bool] = True
place: Optional[Iterable[str]] = None
portrait: Optional[bool] = None
query_eval: Optional[Iterable[str]] = None
regex: Optional[Iterable[Tuple[str, str]]] = None
screenshot: Optional[bool] = None
selected: Optional[bool] = None
exif: Optional[Iterable[Tuple[str, str]]] = None
selfie: Optional[bool] = None
shared: Optional[bool] = None
slow_mo: Optional[bool] = None
time_lapse: Optional[bool] = None
title: Optional[Iterable[str]] = None
to_date: Optional[datetime.datetime] = None
to_time: Optional[datetime.time] = None
uti: Optional[Iterable[str]] = None
uuid: Optional[Iterable[str]] = None
year: Optional[Iterable[int]] = None
def asdict(self):

View File

@@ -8,7 +8,7 @@ import re
def utc_offset_string_to_seconds(utc_offset: str) -> int:
"""match a UTC offset in format ±[hh]:[mm], ±[h]:[mm], or ±[hh][mm] and return number of seconds offset"""
patterns = ["^([+-]?)(\d{1,2}):(\d{2})$", "^([+-]?)(\d{2})(\d{2})$"]
patterns = [r"^([+-]?)(\d{1,2}):(\d{2})$", r"^([+-]?)(\d{2})(\d{2})$"]
for pattern in patterns:
match = re.match(pattern, utc_offset)
if not match:
@@ -56,7 +56,7 @@ def update_datetime(
return dt
def time_string_to_datetime(time: str) -> datetime.datetime:
def time_string_to_datetime(time: str) -> datetime.time:
"""Convert time string to datetime.datetime"""
""" valid time formats:
@@ -74,7 +74,7 @@ def time_string_to_datetime(time: str) -> datetime.datetime:
for dt_format in time_formats:
try:
parsed_dt = datetime.datetime.strptime(time, dt_format)
parsed_dt = datetime.datetime.strptime(time, dt_format).time()
except ValueError as e:
pass
else:

View File

@@ -54,3 +54,8 @@ class Timezone:
def __repr__(self):
return self.name
def __eq__(self, other):
if isinstance(other, Timezone):
return self.timezone == other.timezone
return False

View File

@@ -252,6 +252,10 @@ You can also export photos in a certain date range:
`osxphotos export /path/to/export --from-date "2020-01-01" --to-date "2020-02-28"`
or photos added to the library in the last week:
`osxphotos export /path/to/export --added-in-last "1 week"`
## Converting images to JPEG on export
Photos can store images in many different formats. osxphotos can convert non-JPEG images (for example, RAW photos) to JPEG on export using the `--convert-to-jpeg` option. You can specify the JPEG quality (0: worst, 1.0: best) using `--jpeg-quality`. For example:

View File

@@ -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()

View File

@@ -19,7 +19,7 @@ pyobjc-framework-Metal>=7.3,<9.0
pyobjc-framework-Photos>=7.3,<9.0
pyobjc-framework-Quartz>=7.3,<9.0
pyobjc-framework-Vision>=7.3,<9.0
pytimeparse==1.1.8
pytimeparse2==1.4.0
PyYAML>=5.4.1,<6.0.0
requests>=2.27.1,<3.0.0
rich>=11.2.0,<13.0.0

View File

@@ -95,7 +95,7 @@ setup(
"pyobjc-framework-Photos>=7.3,<9.0",
"pyobjc-framework-Quartz>=7.3,<9.0",
"pyobjc-framework-Vision>=7.3,<9.0",
"pytimeparse==1.1.8",
"pytimeparse2==1.4.0",
"requests>=2.27.1,<3.0.0",
"rich>=11.2.0,<13.0.0",
"rich_theme_manager>=0.11.0",

View File

@@ -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()

View File

@@ -175,6 +175,19 @@ PATH_HEIC_EDITED = (
UUID_IS_REFERENCE = "A1DD1F98-2ECD-431F-9AC9-5AFEFE2D3A5C"
UUID_NOT_REFERENCE = "E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51"
UUID_MOMENT = {
"3DD2C897-F19E-4CA6-8C22-B027D5A71907": {
"uuid": "3DD2C897-F19E-4CA6-8C22-B027D5A71907",
"location": (-34.91889167000001, 138.59686167),
"title": "Adelaide",
"subtitle": "",
"start_date": "2017-06-20T17:18:56.518000+09:30",
"end_date": "2017-06-20T17:18:56.518000+09:30",
"date": "2017-06-20T17:18:56.518000+09:30",
"modification_date": "2020-04-06T15:22:24.595584+09:30",
}
}
@pytest.fixture(scope="module")
def photosdb():
@@ -1125,3 +1138,17 @@ def test_no_adjustments(photosdb):
photo = photosdb.get_photo(UUID_DICT["no_adjustments"])
assert photo.adjustments is None
@pytest.mark.parametrize("info", UUID_MOMENT.values())
def test_moment(photosdb, info):
"""test PhotoInfo.moment"""
photo = photosdb.get_photo(uuid=info["uuid"])
assert photo.moment_info.title == info["title"]
assert photo.moment_info.asdict()["title"] == info["title"]
assert photo.moment_info.subtitle == info["subtitle"]
assert photo.moment_info.location == info["location"]
assert photo.moment_info.start_date.isoformat() == info["start_date"]
assert photo.moment_info.end_date.isoformat() == info["end_date"]
assert photo.moment_info.date.isoformat() == info["date"]
assert photo.moment_info.modification_date.isoformat() == info["modification_date"]

View File

@@ -259,6 +259,19 @@ UUID_DETECTED_TEXT = {
"A92D9C26-3A50-4197-9388-CB5F7DB9FA91": None,
}
UUID_MOMENT = {
"7FD37B5F-6FAA-4DB1-8A29-BF9C37E38091": {
"uuid": "7FD37B5F-6FAA-4DB1-8A29-BF9C37E38091",
"location": (20.687278329999998, -156.44366333),
"title": "Hawaiian Islands",
"subtitle": "",
"start_date": "2019-09-15T18:37:17.287000-10:00",
"end_date": "2019-09-15T18:37:17.287000-10:00",
"date": "2019-09-15T18:37:17.287000-10:00",
"modification_date": "2022-02-04T03:51:25.161460-10:00",
}
}
@pytest.fixture(scope="module")
def photosdb():
@@ -1459,3 +1472,17 @@ def test_detected_text(photosdb):
assert expected_text in detected_text
else:
assert not detected_text
@pytest.mark.parametrize("info", UUID_MOMENT.values())
def test_moment(photosdb, info):
"""test PhotoInfo.moment"""
photo = photosdb.get_photo(uuid=info["uuid"])
assert photo.moment_info.title == info["title"]
assert photo.moment_info.asdict()["title"] == info["title"]
assert photo.moment_info.subtitle == info["subtitle"]
assert photo.moment_info.location == info["location"]
assert photo.moment_info.start_date.isoformat() == info["start_date"]
assert photo.moment_info.end_date.isoformat() == info["end_date"]
assert photo.moment_info.date.isoformat() == info["date"]
assert photo.moment_info.modification_date.isoformat() == info["modification_date"]

View File

@@ -1,5 +1,4 @@
""" Test the command line interface (CLI) """
import datetime
import glob
import json
@@ -90,31 +89,6 @@ UUID_DOWNLOAD_MISSING = "C6C712C5-9316-408D-A3C3-125661422DA9" # IMG_8844.JPG
UUID_FILE = "tests/uuid_from_file.txt"
SKIP_UUID_FILE = "tests/skip_uuid_from_file.txt"
CLI_OUTPUT_NO_SUBCOMMAND = [
"Options:",
"--db <Photos database path> Specify Photos database path. Path to Photos",
"library/database can be specified using either",
"--db or directly as PHOTOS_LIBRARY positional",
"argument.",
"--json Print output in JSON format.",
"-v, --version Show the version and exit.",
"-h, --help Show this message and exit.",
"Commands:",
" albums Print out albums found in the Photos library.",
" dump Print list of all photos & associated info from the Photos",
" export Export photos from the Photos database.",
" help Print help; for help on commands: help <command>.",
" info Print out descriptive info of the Photos library database.",
" install Install Python packages into the same environment as osxphotos",
" keywords Print out keywords found in the Photos library",
" labels Print out image classification labels found in the Photos",
" list Print list of Photos libraries found on the system.",
" persons Print out persons (faces) found in the Photos library.",
" places Print out places found in the Photos library.",
" query Query the Photos database using 1 or more search options; if",
" uninstall Uninstall Python packages from the osxphotos environment",
]
CLI_OUTPUT_QUERY_UUID = '[{"uuid": "D79B8D77-BFFC-460B-9312-034F2877D35B", "filename": "D79B8D77-BFFC-460B-9312-034F2877D35B.jpeg", "original_filename": "Pumkins2.jpg", "date": "2018-09-28T16:07:07-04:00", "description": "Girl holding pumpkin", "title": "I found one!", "keywords": ["Kids"], "albums": ["Pumpkin Farm", "Test Album", "Multi Keyword"], "persons": ["Katie"], "path": "/tests/Test-10.15.7.photoslibrary/originals/D/D79B8D77-BFFC-460B-9312-034F2877D35B.jpeg", "ismissing": false, "hasadjustments": false, "external_edit": false, "favorite": false, "hidden": false, "latitude": 41.256566, "longitude": -95.940257, "path_edited": null, "shared": false, "isphoto": true, "ismovie": false, "uti": "public.jpeg", "burst": false, "live_photo": false, "path_live_photo": null, "iscloudasset": false, "incloud": null}]'
CLI_EXPORT_FILENAMES = [
@@ -1066,11 +1040,9 @@ def test_osxphotos():
runner = CliRunner()
result = runner.invoke(cli_main, [])
output = result.output
assert result.exit_code == 0
for line in CLI_OUTPUT_NO_SUBCOMMAND:
assert line.strip() in output
assert "Print information about osxphotos" in result.output
def test_osxphotos_help_1():
@@ -1078,10 +1050,8 @@ def test_osxphotos_help_1():
runner = CliRunner()
result = runner.invoke(cli_main, ["help"])
output = result.output
assert result.exit_code == 0
for line in CLI_OUTPUT_NO_SUBCOMMAND:
assert line.strip() in output
assert "Print information about osxphotos" in result.output
def test_osxphotos_help_2():
@@ -7108,6 +7078,67 @@ def test_query_function():
assert json_got[0]["original_filename"] == "DSC03584.dng"
def test_query_added_after():
"""test query --added-after"""
runner = CliRunner()
cwd = os.getcwd()
# pylint: disable=not-context-manager
results = runner.invoke(
query,
[
os.path.join(cwd, PHOTOS_DB_15_7),
"--json",
"--added-after",
"2022-02-03",
],
)
assert results.exit_code == 0
json_got = json.loads(results.output)
assert len(json_got) == 4
def test_query_added_before():
"""test query --added-before"""
runner = CliRunner()
cwd = os.getcwd()
# pylint: disable=not-context-manager
results = runner.invoke(
query,
[
os.path.join(cwd, PHOTOS_DB_15_7),
"--json",
"--added-before",
"2019-07-28",
],
)
assert results.exit_code == 0
json_got = json.loads(results.output)
assert len(json_got) == 7
def test_query_added_in_last():
"""test query --added-in-last"""
# Note: ideally, I'd test this with freezegun to verify the time deltas worked but
# freezegun causes osxphotos tests to crash so we just test that the --added-in-last runs without error
runner = CliRunner()
cwd = os.getcwd()
# pylint: disable=not-context-manager
results = runner.invoke(
query,
[
os.path.join(cwd, PHOTOS_DB_15_7),
"--json",
"--added-in-last",
"10 years",
],
)
assert results.exit_code == 0
def test_export_export_dir_template():
"""Test {export_dir} template"""
@@ -7621,3 +7652,123 @@ def test_theme_list():
result = runner.invoke(cli_main, ["theme", "--list"])
assert result.exit_code == 0
assert "Dark" in result.output
def test_export_added_after():
"""test export --added-after"""
runner = CliRunner()
cwd = os.getcwd()
with runner.isolated_filesystem():
result = runner.invoke(
export,
[
".",
"--db",
os.path.join(cwd, PHOTOS_DB_15_7),
"--added-after",
"2022-02-03",
],
)
assert result.exit_code == 0
assert "Exporting 4 photos" in result.output
def test_export_added_before():
"""test export --added-before"""
runner = CliRunner()
cwd = os.getcwd()
with runner.isolated_filesystem():
result = runner.invoke(
export,
[
".",
"--db",
os.path.join(cwd, PHOTOS_DB_15_7),
"--added-before",
"2019-07-28",
],
)
assert result.exit_code == 0
assert "Exporting 7 photos" in result.output
def test_export_added_in_last():
"""test export --added-in-last"""
# can't use freezegun as it causes osxphotos tests to crash so
# just run export with --added-in-last and verify no errors
runner = CliRunner()
cwd = os.getcwd()
with runner.isolated_filesystem():
result = runner.invoke(
export,
[
".",
"--db",
os.path.join(cwd, PHOTOS_DB_15_7),
"--added-in-last",
"10 years",
],
)
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

View File

@@ -0,0 +1,205 @@
""" Test custom click paramater types used by osxphotos CLI"""
import datetime
from bitmath import MB
import pytest
from osxphotos.timezones import Timezone
from click.exceptions import BadParameter
from osxphotos.cli.param_types import (
BitMathSize,
DateOffset,
DateTimeISO8601,
ExportDBType,
FunctionCall,
TemplateString,
TimeISO8601,
TimeOffset,
TimeString,
UTCOffset,
)
def test_date_offset():
"""Test DateOffset"""
date_offset_data = {
"1": datetime.timedelta(days=1),
"1 day": datetime.timedelta(days=1),
"+1 day": datetime.timedelta(days=1),
"1 d": datetime.timedelta(days=1),
"1d": datetime.timedelta(days=1),
"+ 1": datetime.timedelta(days=1),
"+1 day": datetime.timedelta(days=1),
"+ 1": datetime.timedelta(days=1),
"14:30": datetime.timedelta(minutes=14, seconds=30),
"14:30:00": datetime.timedelta(hours=14, minutes=30, seconds=0),
"1 week": datetime.timedelta(days=7),
"2 wk": datetime.timedelta(days=14),
"2 months": datetime.timedelta(days=60),
"1 mos": datetime.timedelta(days=30),
}
for date_offset_str, date_offset_delta in date_offset_data.items():
assert DateOffset().convert(date_offset_str, None, None) == date_offset_delta
def test_date_offset_invalid_format():
"""Test DateOffset with invalid format"""
date_offset_data = [
"1 foo",
"1 day 14",
"day",
]
for date_offset_str in date_offset_data:
with pytest.raises(BadParameter):
DateOffset().convert(date_offset_str, None, None)
def test_time_offset():
"""Test TimeOffset"""
time_offset_data = {
"1": datetime.timedelta(seconds=1),
"1s": datetime.timedelta(seconds=1),
"2 s": datetime.timedelta(seconds=2),
"2 sec": datetime.timedelta(seconds=2),
"3 sec": datetime.timedelta(seconds=3),
"1m": datetime.timedelta(minutes=1),
"1 min": datetime.timedelta(minutes=1),
"1 day": datetime.timedelta(days=1),
"14:30": datetime.timedelta(minutes=14, seconds=30),
"14:30:00": datetime.timedelta(hours=14, minutes=30, seconds=0),
}
for time_offset_str, time_offset_delta in time_offset_data.items():
assert TimeOffset().convert(time_offset_str, None, None) == time_offset_delta
def test_time_offset_invalid_format():
"""Test TimeOffset with invalid format"""
time_offset_data = [
"1 foo",
"1 day 14",
"1 sec 1",
"sec",
]
for time_offset_str in time_offset_data:
with pytest.raises(BadParameter):
TimeOffset().convert(time_offset_str, None, None)
def test_bitmath_size():
"""Test BitMathSize"""
bitmath_size_data = {
"1048576": MB(1.048576),
"1.048576MB": MB(1.048576),
"1 MiB": MB(1.048576),
}
for bitmath_size_str, bitmath_size_int in bitmath_size_data.items():
assert BitMathSize().convert(bitmath_size_str, None, None) == bitmath_size_int
def test_bitmath_size_invalid_format():
"""Test BitMathSize with invalid format"""
bitmath_size_data = [
"1 foo",
"1 mehgabite",
]
for bitmath_size_str in bitmath_size_data:
with pytest.raises(BadParameter):
BitMathSize().convert(bitmath_size_str, None, None)
def test_date_time_iso8601():
"""Test DateTimeISO8601"""
date_time_iso8601_data = {
"2020-01-01T00:00:00": datetime.datetime(2020, 1, 1, 0, 0, 0),
"2020-01-01T00:00:00.000": datetime.datetime(2020, 1, 1, 0, 0, 0),
"2020-01-01": datetime.datetime(2020, 1, 1),
}
for date_time_iso8601_str, date_time_iso8601_dt in date_time_iso8601_data.items():
assert (
DateTimeISO8601().convert(date_time_iso8601_str, None, None)
== date_time_iso8601_dt
)
def test_date_time_iso8601_invalid_format():
"""Test DateTimeISO8601 with invalid format"""
date_time_iso8601_data = [
"20-01-01T00:00:00",
"20-01-1",
]
for date_time_iso8601_str in date_time_iso8601_data:
with pytest.raises(BadParameter):
DateTimeISO8601().convert(date_time_iso8601_str, None, None)
def test_time_iso8601():
"""Test TimeISO8601"""
time_iso8601_data = {
"00:00:00": datetime.time(0, 0, 0),
"00:00:00.000": datetime.time(0, 0, 0),
}
for time_iso8601_str, time_iso8601_dt in time_iso8601_data.items():
assert TimeISO8601().convert(time_iso8601_str, None, None) == time_iso8601_dt
def test_time_iso8601_invalid_format():
"""Test TimeISO8601 with invalid format"""
date_time_iso8601_data = [
"20-01-01T00:00:00",
"20-01-1",
]
for date_time_iso8601_str in date_time_iso8601_data:
with pytest.raises(BadParameter):
TimeISO8601().convert(date_time_iso8601_str, None, None)
def test_timestring():
"""Test TimeString"""
timestring_data = {
"01:02:03": datetime.time(1, 2, 3),
"01:02:03.000": datetime.time(1, 2, 3),
"01:02:03.0000": datetime.time(1, 2, 3),
"01:02": datetime.time(1, 2, 0),
}
for timestring_str, timestring_dt in timestring_data.items():
assert TimeString().convert(timestring_str, None, None) == timestring_dt
def test_timestring_invalid_format():
"""Test TimeString with invalid format"""
timestring_data = [
"20-01-01T00:00:00",
"20-01-1",
]
for timestring_str in timestring_data:
with pytest.raises(BadParameter):
TimeString().convert(timestring_str, None, None)
def test_utcoffset():
"""Test UTCOffset"""
utcoffset_data = {
"+00:00": Timezone(0),
"-00:00": Timezone(-0),
"+01:00": Timezone(3600),
"-01:00": Timezone(-3600),
"+01:30": Timezone(5400),
"-01:30": Timezone(-5400),
}
for utcoffset_str, utcoffset_int in utcoffset_data.items():
assert UTCOffset().convert(utcoffset_str, None, None) == utcoffset_int
def test_utcoffset_invalid_format():
"""Test UTCOffset with invalid format"""
utcoffset_data = [
"20-01-01T00:00:00",
"20-01-1",
]
for utcoffset_str in utcoffset_data:
with pytest.raises(BadParameter):
UTCOffset().convert(utcoffset_str, None, None)

View File

@@ -81,7 +81,7 @@ def test_inspect(photoslib, suspend_capture, output_file):
runner = CliRunner()
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
@@ -101,6 +101,7 @@ def test_date(photoslib, suspend_capture):
"--date",
TEST_DATA["date"]["value"],
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
@@ -122,13 +123,14 @@ def test_date_delta(photoslib, suspend_capture, input_value, expected, output_fi
"--date-delta",
input_value,
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_inspect_output(output_file)
@@ -148,6 +150,7 @@ def test_time(photoslib, suspend_capture, input_value, expected, output_file):
"--time",
input_value,
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
@@ -156,7 +159,7 @@ def test_time(photoslib, suspend_capture, input_value, expected, output_file):
# don't use photo.date as it will return local time instead of the time in the timezone
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_inspect_output(output_file)
@@ -176,13 +179,14 @@ def test_time_delta(photoslib, suspend_capture, input_value, expected, output_fi
"--time-delta",
input_value,
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_inspect_output(output_file)
@@ -206,13 +210,14 @@ def test_time_zone(
"--timezone",
input_value,
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_inspect_output(output_file)
@@ -232,6 +237,7 @@ def test_compare_exif(photoslib, suspend_capture, expected, output_file):
[
"--compare-exif",
"--plain",
"--force",
"-o",
output_file,
],
@@ -258,6 +264,7 @@ def test_compare_exif_add_to_album(photoslib, suspend_capture, expected, album):
"--add-to-album",
album,
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
@@ -282,7 +289,7 @@ def test_compare_exif_3(photoslib, suspend_capture, expected, output_file):
runner = CliRunner()
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
@@ -304,13 +311,14 @@ def test_match(photoslib, suspend_capture, input_value, expected, output_file):
input_value,
"--match-time",
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_inspect_output(output_file)
@@ -324,7 +332,9 @@ def test_push_exif_missing_file():
runner = CliRunner()
result = runner.invoke(
timewarp, ["--push-exif", "--plain", "--verbose"], terminal_width=TERMINAL_WIDTH
timewarp,
["--push-exif", "--plain", "--force", "--verbose"],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
assert "Skipping EXIF update for missing photo" in result.output
@@ -361,6 +371,7 @@ def test_push_exif_1(
time_delta_value,
"--push-exif",
"--plain",
"--force",
]
if match:
cli_args.append("--match-time")
@@ -370,7 +381,7 @@ def test_push_exif_1(
assert result.exit_code == 0
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_inspect_output(output_file)
@@ -403,7 +414,7 @@ def test_push_exif_2(photoslib, suspend_capture, output_file):
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -414,6 +425,7 @@ def test_push_exif_2(photoslib, suspend_capture, output_file):
[
"--push-exif",
"--plain",
"--force",
"--verbose",
],
terminal_width=TERMINAL_WIDTH,
@@ -422,7 +434,7 @@ def test_push_exif_2(photoslib, suspend_capture, output_file):
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -442,14 +454,14 @@ def test_pull_exif_1(photoslib, suspend_capture, output_file):
# update the photo so we know if the data is updated
result = runner.invoke(
timewarp,
["-z", "-0400", "-D", "+1 day", "-m", "-V", "--plain"],
["-z", "-0400", "-D", "+1 day", "-m", "-V", "--plain", "--force"],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -460,6 +472,7 @@ def test_pull_exif_1(photoslib, suspend_capture, output_file):
[
"--pull-exif",
"--plain",
"--force",
"--verbose",
],
terminal_width=TERMINAL_WIDTH,
@@ -468,7 +481,7 @@ def test_pull_exif_1(photoslib, suspend_capture, output_file):
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -493,7 +506,7 @@ def test_pull_exif_no_time(photoslib, suspend_capture, output_file):
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -504,6 +517,7 @@ def test_pull_exif_no_time(photoslib, suspend_capture, output_file):
[
"--pull-exif",
"--plain",
"--force",
"--verbose",
],
terminal_width=TERMINAL_WIDTH,
@@ -512,7 +526,7 @@ def test_pull_exif_no_time(photoslib, suspend_capture, output_file):
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -537,7 +551,7 @@ def test_pull_exif_no_offset(photoslib, suspend_capture, output_file):
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -548,6 +562,7 @@ def test_pull_exif_no_offset(photoslib, suspend_capture, output_file):
[
"--pull-exif",
"--plain",
"--force",
"--verbose",
],
terminal_width=TERMINAL_WIDTH,
@@ -556,7 +571,7 @@ def test_pull_exif_no_offset(photoslib, suspend_capture, output_file):
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -583,7 +598,7 @@ def test_pull_exif_no_data(photoslib, suspend_capture, output_file):
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -594,6 +609,7 @@ def test_pull_exif_no_data(photoslib, suspend_capture, output_file):
[
"--pull-exif",
"--plain",
"--force",
"--verbose",
],
terminal_width=TERMINAL_WIDTH,
@@ -603,7 +619,7 @@ def test_pull_exif_no_data(photoslib, suspend_capture, output_file):
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -622,7 +638,7 @@ def test_pull_exif_no_data_use_file_time(photoslib, suspend_capture, output_file
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -633,6 +649,7 @@ def test_pull_exif_no_data_use_file_time(photoslib, suspend_capture, output_file
[
"--pull-exif",
"--plain",
"--force",
"--verbose",
"--use-file-time",
],
@@ -643,7 +660,7 @@ def test_pull_exif_no_data_use_file_time(photoslib, suspend_capture, output_file
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -668,6 +685,7 @@ def test_video_compare_exif(photoslib, suspend_capture, expected, output_file):
[
"--compare-exif",
"--plain",
"--force",
"-o",
output_file,
],
@@ -695,6 +713,7 @@ def test_video_date_delta(
"--date-delta",
input_value,
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
@@ -702,7 +721,7 @@ def test_video_date_delta(
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_inspect_output(output_file)
@@ -726,13 +745,14 @@ def test_video_time_delta(
"--time-delta",
input_value,
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_inspect_output(output_file)
@@ -752,6 +772,7 @@ def test_video_date(photoslib, suspend_capture, input_value, expected, output_fi
"--date",
input_value,
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
@@ -760,7 +781,7 @@ def test_video_date(photoslib, suspend_capture, input_value, expected, output_fi
# don't use photo.date as it will return local time instead of the time in the timezone
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_inspect_output(output_file)
@@ -780,6 +801,7 @@ def test_video_time(photoslib, suspend_capture, input_value, expected, output_fi
"--time",
input_value,
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
@@ -788,7 +810,7 @@ def test_video_time(photoslib, suspend_capture, input_value, expected, output_fi
# don't use photo.date as it will return local time instead of the time in the timezone
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_inspect_output(output_file)
@@ -812,13 +834,14 @@ def test_video_time_zone(
"--timezone",
input_value,
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_inspect_output(output_file)
@@ -840,13 +863,14 @@ def test_video_match(photoslib, suspend_capture, input_value, expected, output_f
input_value,
"--match-time",
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_inspect_output(output_file)
@@ -865,7 +889,7 @@ def test_video_push_exif(photoslib, suspend_capture, output_file):
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -876,6 +900,7 @@ def test_video_push_exif(photoslib, suspend_capture, output_file):
[
"--push-exif",
"--plain",
"--force",
"--verbose",
],
terminal_width=TERMINAL_WIDTH,
@@ -884,7 +909,7 @@ def test_video_push_exif(photoslib, suspend_capture, output_file):
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -904,14 +929,25 @@ def test_video_pull_exif(photoslib, suspend_capture, output_file):
# update the photo so we know if the data is updated
result = runner.invoke(
timewarp,
["-z", "-0500", "-D", "+1 day", "-T", "-10 hours", "-m", "-V", "--plain"],
[
"-z",
"-0500",
"-D",
"+1 day",
"-T",
"-10 hours",
"-m",
"-V",
"--plain",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -922,6 +958,7 @@ def test_video_pull_exif(photoslib, suspend_capture, output_file):
[
"--pull-exif",
"--plain",
"--force",
"--verbose",
],
terminal_width=TERMINAL_WIDTH,
@@ -930,7 +967,7 @@ def test_video_pull_exif(photoslib, suspend_capture, output_file):
result = runner.invoke(
timewarp,
["--compare-exif", "--plain", "-o", output_file],
["--compare-exif", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_compare_exif(output_file)
@@ -956,13 +993,14 @@ def test_function(photoslib, suspend_capture, output_file):
[
"--function",
"tests/timewarp_function_example.py::get_date_time_timezone",
"--force",
],
terminal_width=TERMINAL_WIDTH,
)
assert result.exit_code == 0
result = runner.invoke(
timewarp,
["--inspect", "--plain", "-o", output_file],
["--inspect", "--plain", "--force", "-o", output_file],
terminal_width=TERMINAL_WIDTH,
)
output_values = parse_inspect_output(output_file)

View File

@@ -180,6 +180,19 @@ PATH_HEIC_EDITED = (
UUID_IS_REFERENCE = "A1DD1F98-2ECD-431F-9AC9-5AFEFE2D3A5C"
UUID_NOT_REFERENCE = "E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51"
UUID_MOMENT = {
"3DD2C897-F19E-4CA6-8C22-B027D5A71907": {
"uuid": "3DD2C897-F19E-4CA6-8C22-B027D5A71907",
"location": (-34.91889167000001, 138.59686167),
"title": "Adelaide",
"subtitle": "",
"start_date": "2017-06-20T17:18:56.518000+09:30",
"end_date": "2017-06-20T17:18:56.518000+09:30",
"date": "2017-06-20T17:18:56.518000+09:30",
"modification_date": "2020-04-06T15:22:24.595584+09:30",
}
}
@pytest.fixture(scope="module")
def photosdb():
@@ -1130,3 +1143,17 @@ def test_no_adjustments(photosdb):
photo = photosdb.get_photo(UUID_DICT["no_adjustments"])
assert photo.adjustments is None
@pytest.mark.parametrize("info", UUID_MOMENT.values())
def test_moment(photosdb, info):
"""test PhotoInfo.moment"""
photo = photosdb.get_photo(uuid=info["uuid"])
assert photo.moment_info.title == info["title"]
assert photo.moment_info.asdict()["title"] == info["title"]
assert photo.moment_info.subtitle == info["subtitle"]
assert photo.moment_info.location == info["location"]
assert photo.moment_info.start_date.isoformat() == info["start_date"]
assert photo.moment_info.end_date.isoformat() == info["end_date"]
assert photo.moment_info.date.isoformat() == info["date"]
assert photo.moment_info.modification_date.isoformat() == info["modification_date"]

View File

@@ -333,7 +333,9 @@ UUID_CONDITIONAL = {
"{photo.score.overall >= 0.7?YES,NO}": ["NO"],
"{photo.score.overall not < 0.7?YES,NO}": ["NO"],
"{folder_album(-) contains Folder1-SubFolder2-AlbumInFolder?YES,NO}": ["YES"],
"{folder_album( - ) contains Folder1 - SubFolder2 - AlbumInFolder?YES,NO}": ["YES"],
"{folder_album( - ) contains Folder1 - SubFolder2 - AlbumInFolder?YES,NO}": [
"YES"
],
"{folder_album(-)[In,] contains Folder1-SubFolder2-AlbumFolder?YES,NO}": [
"YES"
],
@@ -395,6 +397,14 @@ UUID_ALBUM_SEQ = {
},
}
UUID_MOMENT = {
"7FD37B5F-6FAA-4DB1-8A29-BF9C37E38091": {
"templates": {
"{moment}": ["Hawaiian Islands"],
}
}
}
UUID_EMPTY_TITLE = "7783E8E6-9CAC-40F3-BE22-81FB7051C266" # IMG_3092.heic
UUID_EMPTY_TITLE_HAS_DESCRIPTION = "E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51" # wedding.jpg
@@ -1243,3 +1253,12 @@ def test_no_project(photosdb_project):
for template, value in TEMPLATE_VALUES_NO_PROJECT.items():
rendered, _ = photo.render_template(template)
assert rendered == value
def test_moment(photosdb):
"""Test {moment} template"""
for uuid in UUID_MOMENT:
photo = photosdb.get_photo(uuid)
for template, value in UUID_MOMENT[uuid]["templates"].items():
rendered, _ = photo.render_template(template)
assert rendered == value