Compare commits

..

8 Commits

Author SHA1 Message Date
Rhet Turnbull
db5c4a216f Release files for 0.56.6 (#952) 2023-01-22 22:40:50 -08:00
Rhet Turnbull
369fa553e8 Feature timewarp parse date 867 (#951)
* Working on tests for timewarp --parse-date

* Test working for --parse-date

* Refactored date utils out of timewarp.py

* Added timezone to --parse-date, updated tests

* Added cog to README
2023-01-22 22:35:05 -08:00
Rhet Turnbull
29968269ff Feature person favorite 940 (#950)
* Added person favorite for #940

* Added person.feature_less #940 (but not 100% sure it's right yet)

* Added tests for PersonInfo.favorite, PersonInfo.feature_less
2023-01-22 11:53:08 -08:00
Rhet Turnbull
381141bc09 Updated CHANGELOG.md [skip ci] 2023-01-21 14:55:06 -08:00
Rhet Turnbull
caa279e394 Release files for 0.56.5 (#948) 2023-01-21 14:52:15 -08:00
Rhet Turnbull
bd01e41714 Bug timewarp sync 946 (#947)
* Fix --timezone iCloud sync, #946

* ADded tests for timezone fix #946
2023-01-21 14:48:56 -08:00
Rhet Turnbull
32b23a09cb Updated CHANGELOG.md [skip ci] 2023-01-21 10:45:34 -08:00
allcontributors[bot]
4857598324 add djbeadle as a contributor for ideas (#945)
* update README.md [skip ci]

* update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2023-01-21 10:44:10 -08:00
172 changed files with 2475 additions and 419 deletions

View File

@@ -464,6 +464,15 @@
"contributions": [
"doc"
]
},
{
"login": "djbeadle",
"name": "Daniel Beadle",
"avatar_url": "https://avatars.githubusercontent.com/u/6235378?v=4",
"profile": "https://danielbeadle.net",
"contributions": [
"ideas"
]
}
],
"contributorsPerLine": 7,

View File

@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.56.4
current_version = 0.56.6
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
serialize = {major}.{minor}.{patch}

View File

@@ -1581,6 +1581,14 @@ Returns a list of PhotoInfo objects representing all photos the person appears i
Returns a list of [FaceInfo](#faceinfo) objects associated with this person sorted by quality score. Highest quality face is result[0] and lowest quality face is result[n].
#### <a name="personfavorite">`favorite`</a>
Returns True if Person has been marked as a favorite in Photos, otherwise False. Available on Photos 5+ only; on Photos <=4, returns False.
#### <a name="personsortorder">`sort_order`</a>
Returns the sort order for the person in the Photos People view. Available on Photos 5+ only; on Photos <= 4, returns None.
#### `json()`
Returns a json string representation of the PersonInfo instance.
@@ -2025,7 +2033,7 @@ cog.out(get_template_field_table())
|{cr}|A carriage return: '\r'|
|{crlf}|A carriage return + line feed: '\r\n'|
|{tab}|:A tab: '\t'|
|{osxphotos_version}|The osxphotos version, e.g. '0.56.4'|
|{osxphotos_version}|The osxphotos version, e.g. '0.56.6'|
|{osxphotos_cmd_line}|The full command line used to run osxphotos|
|{album}|Album(s) photo is contained in|
|{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder|

View File

@@ -4,6 +4,23 @@ 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.56.5](https://github.com/RhetTbull/osxphotos/compare/v0.56.4...v0.56.5)
> 21 January 2023
- Release files for 0.56.5 [`#948`](https://github.com/RhetTbull/osxphotos/pull/948)
- Bug timewarp sync 946 [`#947`](https://github.com/RhetTbull/osxphotos/pull/947)
- add djbeadle as a contributor for ideas [`#945`](https://github.com/RhetTbull/osxphotos/pull/945)
- Bug timewarp sync 946 (#947) [`#946`](https://github.com/RhetTbull/osxphotos/issues/946)
#### [v0.56.4](https://github.com/RhetTbull/osxphotos/compare/v0.56.3...v0.56.4)
> 21 January 2023
- Updated release files for v0.56.4 [`#944`](https://github.com/RhetTbull/osxphotos/pull/944)
- Updated search info for Ventura, #937 [`#943`](https://github.com/RhetTbull/osxphotos/pull/943)
- Bug slow import 934 [`#942`](https://github.com/RhetTbull/osxphotos/pull/942)
#### [v0.56.3](https://github.com/RhetTbull/osxphotos/compare/v0.56.2...v0.56.3)
> 16 January 2023

View File

@@ -7,7 +7,7 @@
[![Downloads](https://static.pepy.tech/personalized-badge/osxphotos?period=month&units=international_system&left_color=black&right_color=brightgreen&left_text=downloads/month)](https://pepy.tech/project/osxphotos)
[![subreddit](https://img.shields.io/reddit/subreddit-subscribers/osxphotos?style=social)](https://www.reddit.com/r/osxphotos/)
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-48-orange.svg?style=flat)](#contributors)
[![All Contributors](https://img.shields.io/badge/all_contributors-49-orange.svg?style=flat)](#contributors)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
OSXPhotos provides the ability to interact with and query Apple's Photos.app library on macOS. You can query the Photos library database — for example, file name, file path, and metadata such as keywords/tags, persons/faces, albums, etc. You can also easily export both the original and edited photos.
@@ -112,56 +112,68 @@ If you have questions, would like to show off projects created with OSXPhotos, o
This package will install a command line utility called `osxphotos` that allows you to query the Photos database. Alternatively, you can also run the command line utility like this: `python3 -m osxphotos`
<!--[[[cog
from osxphotos.cli import cli_main
from click.testing import CliRunner
runner = CliRunner()
result = runner.invoke(cli_main, ["--help"])
help = result.output.replace("Usage: cli-main", "Usage: osxphotos")
cog.out(
"```\n{}\n```".format(help)
)
]]] -->
```
> osxphotos
Usage: osxphotos [OPTIONS] COMMAND [ARGS]...
osxphotos: query and export your Photos library
osxphotos: the multi-tool for your Photos library
Options:
--db PHOTOS_LIBRARY_PATH 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
--json Print output in JSON format.
-v, --version Show the version and exit.
--db PHOTOS_LIBRARY_PATH 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
--json Print output in JSON format.
-h, --help Show this message and exit.
Commands:
about Print information about osxphotos including license.
albums Print out albums found in the Photos library.
diff Compare two Photos databases and print out differences
docs Open osxphotos documentation in your browser.
dump Print list of all photos & associated info from the Photos...
exiftool Run exiftool on previously exported files to update metadata.
export Export photos from the Photos database.
exportdb Utilities for working with the osxphotos export database
help Print help; for help on commands: help <command>.
import Import photos and videos into Photos.
info Print out descriptive info of the Photos library database.
inspect Interactively inspect photos selected in Photos.
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.
orphans Find orphaned photos in a Photos library
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...
repl Run interactive osxphotos REPL shell (useful for debugging,...
run Run a python file using same environment as osxphotos.
snap Create snapshot of Photos database to use with diff command
theme Manage osxphotos color themes.
timewarp Adjust date/time/timezone of photos in Apple Photos.
tutorial Display osxphotos tutorial.
uninstall Uninstall Python packages from the osxphotos environment
uuid Print out unique IDs (UUID) of photos selected in Photos
version Check for new version of osxphotos.
about Print information about osxphotos including license.
add-locations Add missing location data to photos in Photos.app using...
albums Print out albums found in the Photos library.
diff Compare two Photos databases and print out differences
docs Open osxphotos documentation in your browser.
dump Print list of all photos & associated info from the Photos...
exiftool Run exiftool on previously exported files to update metadata.
export Export photos from the Photos database.
exportdb Utilities for working with the osxphotos export database
help Print help; for help on commands: help <command>.
import Import photos and videos into Photos.
info Print out descriptive info of the Photos library database.
inspect Interactively inspect photos selected in Photos.
install Install Python packages into the same environment as...
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.
orphans Find orphaned photos in a Photos library
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;...
repl Run interactive osxphotos REPL shell (useful for...
run Run a python file using same environment as osxphotos.
snap Create snapshot of Photos database to use with diff command
sync Sync metadata and albums between Photos libraries.
theme Manage osxphotos color themes.
timewarp Adjust date/time/timezone of photos in Apple Photos.
tutorial Display osxphotos tutorial.
uninstall Uninstall Python packages from the osxphotos environment
uuid Print out unique IDs (UUID) of photos selected in Photos
version Check for new version of osxphotos.
```
<!--[[[end]]] -->
To get help on a specific command, use `osxphotos help command_name`, for example, `osxphotos help export` to get help on the `export` command.
@@ -2041,7 +2053,7 @@ Substitution Description
{cr} A carriage return: '\r'
{crlf} A carriage return + line feed: '\r\n'
{tab} :A tab: '\t'
{osxphotos_version} The osxphotos version, e.g. '0.56.4'
{osxphotos_version} The osxphotos version, e.g. '0.56.6'
{osxphotos_cmd_line} The full command line used to run osxphotos
The following substitutions may result in multiple values. Thus if specified
@@ -2525,7 +2537,7 @@ The following template field substitutions are availabe for use the templating s
|{cr}|A carriage return: '\r'|
|{crlf}|A carriage return + line feed: '\r\n'|
|{tab}|:A tab: '\t'|
|{osxphotos_version}|The osxphotos version, e.g. '0.56.4'|
|{osxphotos_version}|The osxphotos version, e.g. '0.56.6'|
|{osxphotos_cmd_line}|The full command line used to run osxphotos|
|{album}|Album(s) photo is contained in|
|{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder|
@@ -2637,6 +2649,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center" valign="top" width="14.28%"><a href="https://qkeddy.github.io/quin-eddy-development-portfolio/"><img src="https://avatars.githubusercontent.com/u/9737814?v=4?s=75" width="75px;" alt="Quin Eddy"/><br /><sub><b>Quin Eddy</b></sub></a><br /><a href="#ideas-qkeddy" title="Ideas, Planning, & Feedback">🤔</a> <a href="#data-qkeddy" title="Data">🔣</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/johnsturgeon"><img src="https://avatars.githubusercontent.com/u/9746310?v=4?s=75" width="75px;" alt="John Sturgeon"/><br /><sub><b>John Sturgeon</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Ajohnsturgeon" title="Bug reports">🐛</a> <a href="https://github.com/RhetTbull/osxphotos/commits?author=johnsturgeon" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mave2k"><img src="https://avatars.githubusercontent.com/u/8629837?v=4?s=75" width="75px;" alt="mave2k"/><br /><sub><b>mave2k</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/commits?author=mave2k" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://danielbeadle.net"><img src="https://avatars.githubusercontent.com/u/6235378?v=4?s=75" width="75px;" alt="Daniel Beadle"/><br /><sub><b>Daniel Beadle</b></sub></a><br /><a href="#ideas-djbeadle" title="Ideas, Planning, & Feedback">🤔</a></td>
</tr>
</tbody>
</table>

View File

@@ -12,6 +12,7 @@ cog -d -o osxphotos/phototemplate.md osxphotos/phototemplate.cog.md
echo "Updating README.md"
python3 utils/update_readme.py
cog -r README.md
echo "Updating API_README.md"
cog -r API_README.md
@@ -53,4 +54,4 @@ ARCHSTR=$(uname -m)
ZIPNAME=osxphotos_MacOS_exe_darwin_${ARCHSTR}_v${OSXPHOTOSVERSION}.zip
echo "Zipping CLI executable to $ZIPNAME"
cd dist && zip $ZIPNAME osxphotos && cd ..
rm dist/osxphotos
rm dist/osxphotos

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: d798209f7408880c3b51365f4e8b8085
config: 825fec5d85827d180b8ee7b12122503b
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-5.3.0, furo 2022.09.29"/>
<title>Overview: module code - osxphotos 0.56.4 documentation</title>
<title>Overview: module code - osxphotos 0.56.6 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<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.56.4 documentation</div></a>
<a href="../index.html"><div class="brand">osxphotos 0.56.6 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -146,7 +146,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="../index.html">
<span class="sidebar-brand-text">osxphotos 0.56.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.6 documentation</span>
</a><form class="sidebar-search-container" method="get" action="../search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">

View File

@@ -1,13 +1,13 @@
<!doctype html>
<html class="no-js">
<html class="no-js" lang="en">
<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" />
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
<title>osxphotos.personinfo - osxphotos 0.50.4 documentation</title>
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
<title>osxphotos.personinfo - osxphotos 0.56.5 documentation</title>
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=68f4518137b9aefe99b631505a2064c3c42c9852" />
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
@@ -123,7 +123,7 @@
</label>
</div>
<div class="header-center">
<a href="../../index.html"><div class="brand">osxphotos 0.50.4 documentation</div></a>
<a href="../../index.html"><div class="brand">osxphotos 0.56.5 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -146,7 +146,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
<span class="sidebar-brand-text">osxphotos 0.50.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.5 documentation</span>
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
@@ -179,7 +179,8 @@
</svg>
<span>Back to top</span>
</a>
<div class="content-icon-container"><div class="theme-toggle-container theme-toggle-content">
<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>
@@ -194,25 +195,27 @@
</div>
<article role="main">
<h1>Source code for osxphotos.personinfo</h1><div class="highlight"><pre>
<span></span><span class="sd">""" PhotoInfo and FaceInfo classes to expose info about persons and faces in the Photos library """</span>
<span></span><span class="sd">&quot;&quot;&quot; PhotoInfo and FaceInfo classes to expose info about persons and faces in the Photos library &quot;&quot;&quot;</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">math</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>
<span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="n">cached_property</span>
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"PersonInfo"</span><span class="p">,</span> <span class="s2">"FaceInfo"</span><span class="p">,</span> <span class="s2">"rotate_image_point"</span><span class="p">]</span>
<span class="kn">import</span> <span class="nn">osxphotos</span>
<span class="n">MWG_RS_Area</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s2">"MWG_RS_Area"</span><span class="p">,</span> <span class="p">[</span><span class="s2">"x"</span><span class="p">,</span> <span class="s2">"y"</span><span class="p">,</span> <span class="s2">"h"</span><span class="p">,</span> <span class="s2">"w"</span><span class="p">])</span>
<span class="n">MPRI_Reg_Rect</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s2">"MPRI_Reg_Rect"</span><span class="p">,</span> <span class="p">[</span><span class="s2">"x"</span><span class="p">,</span> <span class="s2">"y"</span><span class="p">,</span> <span class="s2">"h"</span><span class="p">,</span> <span class="s2">"w"</span><span class="p">])</span>
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;PersonInfo&quot;</span><span class="p">,</span> <span class="s2">&quot;FaceInfo&quot;</span><span class="p">,</span> <span class="s2">&quot;rotate_image_point&quot;</span><span class="p">]</span>
<span class="n">MWG_RS_Area</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s2">&quot;MWG_RS_Area&quot;</span><span class="p">,</span> <span class="p">[</span><span class="s2">&quot;x&quot;</span><span class="p">,</span> <span class="s2">&quot;y&quot;</span><span class="p">,</span> <span class="s2">&quot;h&quot;</span><span class="p">,</span> <span class="s2">&quot;w&quot;</span><span class="p">])</span>
<span class="n">MPRI_Reg_Rect</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s2">&quot;MPRI_Reg_Rect&quot;</span><span class="p">,</span> <span class="p">[</span><span class="s2">&quot;x&quot;</span><span class="p">,</span> <span class="s2">&quot;y&quot;</span><span class="p">,</span> <span class="s2">&quot;h&quot;</span><span class="p">,</span> <span class="s2">&quot;w&quot;</span><span class="p">])</span>
<div class="viewcode-block" id="PersonInfo"><a class="viewcode-back" href="../../reference.html#osxphotos.PersonInfo">[docs]</a><span class="k">class</span> <span class="nc">PersonInfo</span><span class="p">:</span>
<span class="sd">"""Info about a person in the Photos library"""</span>
<span class="sd">&quot;&quot;&quot;Info about a person in the Photos library&quot;&quot;&quot;</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="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">pk</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="sd">"""Creates a new PersonInfo instance</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">db</span><span class="p">:</span> <span class="s2">&quot;osxphotos.PhotosDB&quot;</span><span class="p">,</span> <span class="n">pk</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Creates a new PersonInfo instance</span>
<span class="sd"> Arguments:</span>
<span class="sd"> db: instance of PhotosDB object</span>
@@ -220,16 +223,16 @@
<span class="sd"> Returns:</span>
<span class="sd"> PersonInfo instance</span>
<span class="sd"> """</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">pk</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="p">:</span> <span class="s2">&quot;osxphotos.PhotosDB&quot;</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="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="n">pk</span>
<span class="n">person</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">_dbpersons_pk</span><span class="p">[</span><span class="n">pk</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">uuid</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"uuid"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"fullname"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">display_name</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"displayname"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">keyface</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"keyface"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">facecount</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"facecount"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">uuid</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">&quot;uuid&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">&quot;fullname&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">display_name</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">&quot;displayname&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">keyface</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">&quot;keyface&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">facecount</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">&quot;facecount&quot;</span><span class="p">]</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">keyphoto</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
@@ -237,9 +240,9 @@
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_keyphoto</span>
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
<span class="n">person</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">_dbpersons_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="k">if</span> <span class="n">person</span><span class="p">[</span><span class="s2">"photo_uuid"</span><span class="p">]:</span>
<span class="k">if</span> <span class="n">person</span><span class="p">[</span><span class="s2">&quot;photo_uuid&quot;</span><span class="p">]:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">key_photo</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">get_photo</span><span class="p">(</span><span class="n">person</span><span class="p">[</span><span class="s2">"photo_uuid"</span><span class="p">])</span>
<span class="n">key_photo</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">get_photo</span><span class="p">(</span><span class="n">person</span><span class="p">[</span><span class="s2">&quot;photo_uuid&quot;</span><span class="p">])</span>
<span class="k">except</span> <span class="ne">IndexError</span><span class="p">:</span>
<span class="n">key_photo</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">else</span><span class="p">:</span>
@@ -249,14 +252,14 @@
<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">"""Returns list of PhotoInfo objects associated with this person"""</span>
<span class="sd">&quot;&quot;&quot;Returns list of PhotoInfo objects associated with this person&quot;&quot;&quot;</span>
<span class="k">return</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="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbfaces_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="nd">@property</span>
<span class="k">def</span> <span class="nf">face_info</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Returns a list of FaceInfo objects associated with this person sorted by quality score</span>
<span class="sd">&quot;&quot;&quot;Returns a list of FaceInfo objects associated with this person sorted by quality score</span>
<span class="sd"> Highest quality face is result[0] and lowest quality face is result[n]</span>
<span class="sd"> """</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">faces</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_faceinfo_person</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="k">return</span> <span class="nb">sorted</span><span class="p">(</span>
@@ -268,30 +271,60 @@
<span class="c1"># no faces</span>
<span class="k">return</span> <span class="p">[]</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">favorite</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Returns True if person is a favorite, False otherwise; Photos 5+ only; returns False on Photos &lt;= 4&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbpersons_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">&quot;type&quot;</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">sort_order</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Returns sort order of person; favorite persons are sorted before non-favorite persons&quot;; Photos 5+ only; returns 0 on Photos &lt;= 4&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbpersons_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">&quot;manualorder&quot;</span><span class="p">]</span>
<span class="nd">@cached_property</span>
<span class="k">def</span> <span class="nf">feature_less</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Returns True if person has been marked as &quot;Feature This Person Less&quot; in Photos, False otherwise; Photos 8+ only; returns False on Photos &lt;= 7&quot;&quot;&quot;</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">photos_version</span> <span class="o">&lt;</span> <span class="mi">8</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">if</span> <span class="n">results</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">execute</span><span class="p">(</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> SELECT ZTYPE</span>
<span class="sd"> FROM ZUSERFEEDBACK</span>
<span class="sd"> WHERE ZPERSON = ?</span>
<span class="sd"> &quot;&quot;&quot;</span><span class="p">,</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="p">)</span><span class="o">.</span><span class="n">fetchone</span><span class="p">():</span>
<span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">return</span> <span class="kc">False</span>
<div class="viewcode-block" id="PersonInfo.asdict"><a class="viewcode-back" href="../../reference.html#osxphotos.PersonInfo.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 dictionary representation of class instance"""</span>
<span class="sd">&quot;&quot;&quot;Returns dictionary representation of class instance&quot;&quot;&quot;</span>
<span class="n">keyphoto</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">keyphoto</span><span class="o">.</span><span class="n">uuid</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">keyphoto</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="kc">None</span>
<span class="k">return</span> <span class="p">{</span>
<span class="s2">"uuid"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="p">,</span>
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
<span class="s2">"displayname"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">display_name</span><span class="p">,</span>
<span class="s2">"keyface"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">keyface</span><span class="p">,</span>
<span class="s2">"facecount"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">facecount</span><span class="p">,</span>
<span class="s2">"keyphoto"</span><span class="p">:</span> <span class="n">keyphoto</span><span class="p">,</span>
<span class="s2">&quot;uuid&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="p">,</span>
<span class="s2">&quot;name&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
<span class="s2">&quot;displayname&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">display_name</span><span class="p">,</span>
<span class="s2">&quot;keyface&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">keyface</span><span class="p">,</span>
<span class="s2">&quot;facecount&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">facecount</span><span class="p">,</span>
<span class="s2">&quot;keyphoto&quot;</span><span class="p">:</span> <span class="n">keyphoto</span><span class="p">,</span>
<span class="s2">&quot;favorite&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">favorite</span><span class="p">,</span>
<span class="s2">&quot;sort_order&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">sort_order</span><span class="p">,</span>
<span class="s2">&quot;feature_less&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">feature_less</span><span class="p">,</span>
<span class="p">}</span></div>
<div class="viewcode-block" id="PersonInfo.json"><a class="viewcode-back" href="../../reference.html#osxphotos.PersonInfo.json">[docs]</a> <span class="k">def</span> <span class="nf">json</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Returns JSON representation of class instance"""</span>
<span class="sd">&quot;&quot;&quot;Returns JSON representation of class instance&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">asdict</span><span class="p">())</span></div>
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="sa">f</span><span class="s2">"PersonInfo(name=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">, display_name=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">display_name</span><span class="si">}</span><span class="s2">, uuid=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="si">}</span><span class="s2">, facecount=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">facecount</span><span class="si">}</span><span class="s2">)"</span>
<span class="k">return</span> <span class="sa">f</span><span class="s2">&quot;PersonInfo(name=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">, display_name=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">display_name</span><span class="si">}</span><span class="s2">, uuid=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="si">}</span><span class="s2">, facecount=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">facecount</span><span class="si">}</span><span class="s2">)&quot;</span>
<span class="k">def</span> <span class="fm">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span>
<span class="nb">all</span><span class="p">(</span>
<span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="o">==</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span>
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"_db"</span><span class="p">,</span> <span class="s2">"_pk"</span><span class="p">]</span>
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">&quot;_db&quot;</span><span class="p">,</span> <span class="s2">&quot;_pk&quot;</span><span class="p">]</span>
<span class="p">)</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>
<span class="k">else</span> <span class="kc">False</span>
@@ -302,10 +335,10 @@
<span class="k">class</span> <span class="nc">FaceInfo</span><span class="p">:</span>
<span class="sd">"""Info about a face in the Photos library"""</span>
<span class="sd">&quot;&quot;&quot;Info about a face in the Photos library&quot;&quot;&quot;</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="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">pk</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="sd">"""Creates a new FaceInfo instance</span>
<span class="sd">&quot;&quot;&quot;Creates a new FaceInfo instance</span>
<span class="sd"> Arguments:</span>
<span class="sd"> db: instance of PhotosDB object</span>
@@ -313,59 +346,59 @@
<span class="sd"> Returns:</span>
<span class="sd"> FaceInfo instance</span>
<span class="sd"> """</span>
<span class="sd"> &quot;&quot;&quot;</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">pk</span>
<span class="n">face</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_faceinfo_pk</span><span class="p">[</span><span class="n">pk</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_info</span> <span class="o">=</span> <span class="n">face</span>
<span class="bp">self</span><span class="o">.</span><span class="n">uuid</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"uuid"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"fullname"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"asset_uuid"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_person_pk</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"person"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">center_x</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"centerx"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">center_y</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"centery"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"size"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">quality</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"quality"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">source_width</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"sourcewidth"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">source_height</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"sourceheight"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">has_smile</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"has_smile"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">manual</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"manual"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">face_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"facetype"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">age_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"agetype"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">eye_makeup_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"eyemakeuptype"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">eye_state</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"eyestate"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">facial_hair_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"facialhairtype"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">gender_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"gendertype"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">glasses_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"glassestype"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">hair_color_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"haircolortype"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">intrash</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"intrash"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lip_makeup_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"lipmakeuptype"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">smile_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"smiletype"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">uuid</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;uuid&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;fullname&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;asset_uuid&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_person_pk</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;person&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">center_x</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;centerx&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">center_y</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;centery&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;size&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">quality</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;quality&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">source_width</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;sourcewidth&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">source_height</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;sourceheight&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">has_smile</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;has_smile&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">manual</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;manual&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">face_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;facetype&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">age_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;agetype&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">eye_makeup_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;eyemakeuptype&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">eye_state</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;eyestate&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">facial_hair_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;facialhairtype&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">gender_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;gendertype&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">glasses_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;glassestype&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">hair_color_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;haircolortype&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">intrash</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;intrash&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lip_makeup_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;lipmakeuptype&quot;</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">smile_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">&quot;smiletype&quot;</span><span class="p">]</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">center</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Coordinates, in PIL format, for center of face</span>
<span class="sd">&quot;&quot;&quot;Coordinates, in PIL format, for center of face</span>
<span class="sd"> Returns:</span>
<span class="sd"> tuple of coordinates in form (x, y)</span>
<span class="sd"> """</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_make_point</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_y</span><span class="p">))</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">size_pixels</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Size of face in pixels (centered around center_x, center_y)</span>
<span class="sd">&quot;&quot;&quot;Size of face in pixels (centered around center_x, center_y)</span>
<span class="sd"> Returns:</span>
<span class="sd"> size, in int pixels, of a circle drawn around the center of the face</span>
<span class="sd"> """</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">photo</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span>
<span class="n">size_reference</span> <span class="o">=</span> <span class="n">photo</span><span class="o">.</span><span class="n">width</span> <span class="k">if</span> <span class="n">photo</span><span class="o">.</span><span class="n">width</span> <span class="o">&gt;</span> <span class="n">photo</span><span class="o">.</span><span class="n">height</span> <span class="k">else</span> <span class="n">photo</span><span class="o">.</span><span class="n">height</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">*</span> <span class="n">size_reference</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">person_info</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""PersonInfo instance for person associated with this face"""</span>
<span class="sd">&quot;&quot;&quot;PersonInfo instance for person associated with this face&quot;&quot;&quot;</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">_person</span>
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
@@ -374,18 +407,18 @@
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">photo</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""PhotoInfo instance associated with this face"""</span>
<span class="sd">&quot;&quot;&quot;PhotoInfo instance associated with this face&quot;&quot;&quot;</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">_photo</span>
<span class="k">except</span> <span class="ne">AttributeError</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="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">get_photo</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</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="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Could not get photo for uuid: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Could not get photo for uuid: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photo</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">mwg_rs_area</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Get coordinates for Metadata Working Group Region Area.</span>
<span class="sd">&quot;&quot;&quot;Get coordinates for Metadata Working Group Region Area.</span>
<span class="sd"> Returns:</span>
<span class="sd"> MWG_RS_Area named tuple with x, y, h, w where:</span>
@@ -396,7 +429,7 @@
<span class="sd"> Reference:</span>
<span class="sd"> https://photo.stackexchange.com/questions/106410/how-does-xmp-define-the-face-region</span>
<span class="sd"> """</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_y</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fix_orientation</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
@@ -411,7 +444,7 @@
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">mpri_reg_rect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Get coordinates for Microsoft Photo Region Rectangle.</span>
<span class="sd">&quot;&quot;&quot;Get coordinates for Microsoft Photo Region Rectangle.</span>
<span class="sd"> Returns:</span>
<span class="sd"> MPRI_Reg_Rect named tuple with x, y, h, w where:</span>
@@ -422,7 +455,7 @@
<span class="sd"> Reference:</span>
<span class="sd"> https://docs.microsoft.com/en-us/windows/win32/wic/-wic-people-tagging</span>
<span class="sd"> """</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_y</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fix_orientation</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
@@ -440,13 +473,13 @@
<span class="k">return</span> <span class="n">MPRI_Reg_Rect</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">h</span><span class="p">,</span> <span class="n">w</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">face_rect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Get face rectangle coordinates for current version of the associated image</span>
<span class="sd">&quot;&quot;&quot;Get face rectangle coordinates for current version of the associated image</span>
<span class="sd"> If image has been edited, rectangle applies to edited version, otherwise original version</span>
<span class="sd"> Coordinates in format and reference frame used by PIL</span>
<span class="sd"> Returns:</span>
<span class="sd"> list [(x0, x1), (y0, y1)] of coordinates in reference frame used by PIL</span>
<span class="sd"> """</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">photo</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span>
<span class="n">size_reference</span> <span class="o">=</span> <span class="n">photo</span><span class="o">.</span><span class="n">width</span> <span class="k">if</span> <span class="n">photo</span><span class="o">.</span><span class="n">width</span> <span class="o">&gt;</span> <span class="n">photo</span><span class="o">.</span><span class="n">height</span> <span class="k">else</span> <span class="n">photo</span><span class="o">.</span><span class="n">height</span>
<span class="n">radius</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span> <span class="o">*</span> <span class="n">size_reference</span>
@@ -456,34 +489,34 @@
<span class="k">return</span> <span class="p">[(</span><span class="n">x0</span><span class="p">,</span> <span class="n">y0</span><span class="p">),</span> <span class="p">(</span><span class="n">x1</span><span class="p">,</span> <span class="n">y1</span><span class="p">)]</span>
<span class="k">def</span> <span class="nf">roll_pitch_yaw</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Roll, pitch, yaw of face in radians as tuple"""</span>
<span class="sd">&quot;&quot;&quot;Roll, pitch, yaw of face in radians as tuple&quot;&quot;&quot;</span>
<span class="n">info</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_info</span>
<span class="n">roll</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">info</span><span class="p">[</span><span class="s2">"roll"</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">info</span><span class="p">[</span><span class="s2">"roll"</span><span class="p">]</span>
<span class="n">pitch</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">info</span><span class="p">[</span><span class="s2">"pitch"</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">info</span><span class="p">[</span><span class="s2">"pitch"</span><span class="p">]</span>
<span class="n">yaw</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">info</span><span class="p">[</span><span class="s2">"yaw"</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">info</span><span class="p">[</span><span class="s2">"yaw"</span><span class="p">]</span>
<span class="n">roll</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">info</span><span class="p">[</span><span class="s2">&quot;roll&quot;</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">info</span><span class="p">[</span><span class="s2">&quot;roll&quot;</span><span class="p">]</span>
<span class="n">pitch</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">info</span><span class="p">[</span><span class="s2">&quot;pitch&quot;</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">info</span><span class="p">[</span><span class="s2">&quot;pitch&quot;</span><span class="p">]</span>
<span class="n">yaw</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">info</span><span class="p">[</span><span class="s2">&quot;yaw&quot;</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">info</span><span class="p">[</span><span class="s2">&quot;yaw&quot;</span><span class="p">]</span>
<span class="k">return</span> <span class="p">(</span><span class="n">roll</span><span class="p">,</span> <span class="n">pitch</span><span class="p">,</span> <span class="n">yaw</span><span class="p">)</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">roll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Return roll angle in radians of the face region"""</span>
<span class="sd">&quot;&quot;&quot;Return roll angle in radians of the face region&quot;&quot;&quot;</span>
<span class="n">roll</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">roll_pitch_yaw</span><span class="p">()</span>
<span class="k">return</span> <span class="n">roll</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">pitch</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Return pitch angle in radians of the face region"""</span>
<span class="sd">&quot;&quot;&quot;Return pitch angle in radians of the face region&quot;&quot;&quot;</span>
<span class="n">_</span><span class="p">,</span> <span class="n">pitch</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">roll_pitch_yaw</span><span class="p">()</span>
<span class="k">return</span> <span class="n">pitch</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">yaw</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Return yaw angle in radians of the face region"""</span>
<span class="sd">&quot;&quot;&quot;Return yaw angle in radians of the face region&quot;&quot;&quot;</span>
<span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">yaw</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">roll_pitch_yaw</span><span class="p">()</span>
<span class="k">return</span> <span class="n">yaw</span>
<span class="k">def</span> <span class="nf">_fix_orientation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">xy</span><span class="p">):</span>
<span class="sd">"""Translate an (x, y) tuple based on image orientation</span>
<span class="sd">&quot;&quot;&quot;Translate an (x, y) tuple based on image orientation</span>
<span class="sd"> Arguments:</span>
<span class="sd"> xy: tuple of (x, y) coordinates for point to translate</span>
@@ -491,7 +524,7 @@
<span class="sd"> Returns:</span>
<span class="sd"> (x, y) tuple of translated coordinates</span>
<span class="sd"> """</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="c1"># Reference: https://github.com/neilpa/phace/blob/7594776480505d0c389688a42099c94ac5d34f3f/cmd/phace/draw.go#L79-L94</span>
<span class="n">orientation</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">orientation</span>
@@ -515,15 +548,15 @@
<span class="k">elif</span> <span class="n">orientation</span> <span class="o">==</span> <span class="mi">8</span><span class="p">:</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">y</span><span class="p">,</span> <span class="n">x</span>
<span class="k">elif</span> <span class="n">orientation</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="c1"># set by osxphotos if adjusted orientation cannot be read, assume it's 1</span>
<span class="c1"># set by osxphotos if adjusted orientation cannot be read, assume it&#39;s 1</span>
<span class="n">y</span> <span class="o">=</span> <span class="mf">1.0</span> <span class="o">-</span> <span class="n">y</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unhandled orientation: </span><span class="si">{</span><span class="n">orientation</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Unhandled orientation: </span><span class="si">{</span><span class="n">orientation</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">return</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_make_point</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">xy</span><span class="p">):</span>
<span class="sd">"""Translate an (x, y) tuple based on image orientation</span>
<span class="sd">&quot;&quot;&quot;Translate an (x, y) tuple based on image orientation</span>
<span class="sd"> and convert to image coordinates</span>
<span class="sd"> Arguments:</span>
@@ -532,7 +565,7 @@
<span class="sd"> Returns:</span>
<span class="sd"> (x, y) tuple of translated coordinates in pixels in PIL format/reference frame</span>
<span class="sd"> """</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="c1"># Reference: https://github.com/neilpa/phace/blob/7594776480505d0c389688a42099c94ac5d34f3f/cmd/phace/draw.go#L79-L94</span>
<span class="n">orientation</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">orientation</span>
@@ -544,7 +577,7 @@
<span class="k">return</span> <span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">x</span> <span class="o">*</span> <span class="n">dx</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">y</span> <span class="o">*</span> <span class="n">dy</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">_make_point_with_rotation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">xy</span><span class="p">):</span>
<span class="sd">"""Translate an (x, y) tuple based on image orientation and rotation</span>
<span class="sd">&quot;&quot;&quot;Translate an (x, y) tuple based on image orientation and rotation</span>
<span class="sd"> and convert to image coordinates</span>
<span class="sd"> Arguments:</span>
@@ -553,7 +586,7 @@
<span class="sd"> Returns:</span>
<span class="sd"> (x, y) tuple of translated coordinates in pixels in PIL format/reference frame</span>
<span class="sd"> """</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="c1"># convert to image coordinates</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_make_point</span><span class="p">(</span><span class="n">xy</span><span class="p">)</span>
@@ -566,58 +599,58 @@
<span class="k">return</span> <span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">xr</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">yr</span><span class="p">))</span>
<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 dict representation of class instance"""</span>
<span class="sd">&quot;&quot;&quot;Returns dict representation of class instance&quot;&quot;&quot;</span>
<span class="n">roll</span><span class="p">,</span> <span class="n">pitch</span><span class="p">,</span> <span class="n">yaw</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">roll_pitch_yaw</span><span class="p">()</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">"uuid"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="p">,</span>
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
<span class="s2">"asset_uuid"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span><span class="p">,</span>
<span class="s2">"_person_pk"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_person_pk</span><span class="p">,</span>
<span class="s2">"center_x"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="p">,</span>
<span class="s2">"center_y"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_y</span><span class="p">,</span>
<span class="s2">"center"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">center</span><span class="p">,</span>
<span class="s2">"size"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">,</span>
<span class="s2">"face_rect"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">face_rect</span><span class="p">(),</span>
<span class="s2">"mpri_reg_rect"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">mpri_reg_rect</span><span class="o">.</span><span class="n">_asdict</span><span class="p">(),</span>
<span class="s2">"mwg_rs_area"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">mwg_rs_area</span><span class="o">.</span><span class="n">_asdict</span><span class="p">(),</span>
<span class="s2">"roll"</span><span class="p">:</span> <span class="n">roll</span><span class="p">,</span>
<span class="s2">"pitch"</span><span class="p">:</span> <span class="n">pitch</span><span class="p">,</span>
<span class="s2">"yaw"</span><span class="p">:</span> <span class="n">yaw</span><span class="p">,</span>
<span class="s2">"quality"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">quality</span><span class="p">,</span>
<span class="s2">"source_width"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">source_width</span><span class="p">,</span>
<span class="s2">"source_height"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">source_height</span><span class="p">,</span>
<span class="s2">"has_smile"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">has_smile</span><span class="p">,</span>
<span class="s2">"manual"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">manual</span><span class="p">,</span>
<span class="s2">"face_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">face_type</span><span class="p">,</span>
<span class="s2">"age_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">age_type</span><span class="p">,</span>
<span class="s2">"eye_makeup_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">eye_makeup_type</span><span class="p">,</span>
<span class="s2">"eye_state"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">eye_state</span><span class="p">,</span>
<span class="s2">"facial_hair_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">facial_hair_type</span><span class="p">,</span>
<span class="s2">"gender_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">gender_type</span><span class="p">,</span>
<span class="s2">"glasses_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">glasses_type</span><span class="p">,</span>
<span class="s2">"hair_color_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">hair_color_type</span><span class="p">,</span>
<span class="s2">"intrash"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">intrash</span><span class="p">,</span>
<span class="s2">"lip_makeup_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">lip_makeup_type</span><span class="p">,</span>
<span class="s2">"smile_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">smile_type</span><span class="p">,</span>
<span class="s2">&quot;_pk&quot;</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">&quot;uuid&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="p">,</span>
<span class="s2">&quot;name&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
<span class="s2">&quot;asset_uuid&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span><span class="p">,</span>
<span class="s2">&quot;_person_pk&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_person_pk</span><span class="p">,</span>
<span class="s2">&quot;center_x&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="p">,</span>
<span class="s2">&quot;center_y&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_y</span><span class="p">,</span>
<span class="s2">&quot;center&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">center</span><span class="p">,</span>
<span class="s2">&quot;size&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">,</span>
<span class="s2">&quot;face_rect&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">face_rect</span><span class="p">(),</span>
<span class="s2">&quot;mpri_reg_rect&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">mpri_reg_rect</span><span class="o">.</span><span class="n">_asdict</span><span class="p">(),</span>
<span class="s2">&quot;mwg_rs_area&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">mwg_rs_area</span><span class="o">.</span><span class="n">_asdict</span><span class="p">(),</span>
<span class="s2">&quot;roll&quot;</span><span class="p">:</span> <span class="n">roll</span><span class="p">,</span>
<span class="s2">&quot;pitch&quot;</span><span class="p">:</span> <span class="n">pitch</span><span class="p">,</span>
<span class="s2">&quot;yaw&quot;</span><span class="p">:</span> <span class="n">yaw</span><span class="p">,</span>
<span class="s2">&quot;quality&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">quality</span><span class="p">,</span>
<span class="s2">&quot;source_width&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">source_width</span><span class="p">,</span>
<span class="s2">&quot;source_height&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">source_height</span><span class="p">,</span>
<span class="s2">&quot;has_smile&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">has_smile</span><span class="p">,</span>
<span class="s2">&quot;manual&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">manual</span><span class="p">,</span>
<span class="s2">&quot;face_type&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">face_type</span><span class="p">,</span>
<span class="s2">&quot;age_type&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">age_type</span><span class="p">,</span>
<span class="s2">&quot;eye_makeup_type&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">eye_makeup_type</span><span class="p">,</span>
<span class="s2">&quot;eye_state&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">eye_state</span><span class="p">,</span>
<span class="s2">&quot;facial_hair_type&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">facial_hair_type</span><span class="p">,</span>
<span class="s2">&quot;gender_type&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">gender_type</span><span class="p">,</span>
<span class="s2">&quot;glasses_type&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">glasses_type</span><span class="p">,</span>
<span class="s2">&quot;hair_color_type&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">hair_color_type</span><span class="p">,</span>
<span class="s2">&quot;intrash&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">intrash</span><span class="p">,</span>
<span class="s2">&quot;lip_makeup_type&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">lip_makeup_type</span><span class="p">,</span>
<span class="s2">&quot;smile_type&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">smile_type</span><span class="p">,</span>
<span class="p">}</span>
<span class="k">def</span> <span class="nf">json</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""Return JSON representation of FaceInfo instance"""</span>
<span class="sd">&quot;&quot;&quot;Return JSON representation of FaceInfo instance&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">asdict</span><span class="p">())</span>
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="sa">f</span><span class="s2">"FaceInfo(uuid=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="si">}</span><span class="s2">, center_x=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="si">}</span><span class="s2">, center_y = </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">center_y</span><span class="si">}</span><span class="s2">, size=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="si">}</span><span class="s2">, person=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">, asset_uuid=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span><span class="si">}</span><span class="s2">)"</span>
<span class="k">return</span> <span class="sa">f</span><span class="s2">&quot;FaceInfo(uuid=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="si">}</span><span class="s2">, center_x=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="si">}</span><span class="s2">, center_y = </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">center_y</span><span class="si">}</span><span class="s2">, size=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="si">}</span><span class="s2">, person=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">, asset_uuid=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span><span class="si">}</span><span class="s2">)&quot;</span>
<span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="sa">f</span><span class="s2">"FaceInfo(db=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="si">}</span><span class="s2">, pk=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_pk</span><span class="si">}</span><span class="s2">)"</span>
<span class="k">return</span> <span class="sa">f</span><span class="s2">&quot;FaceInfo(db=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="si">}</span><span class="s2">, pk=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_pk</span><span class="si">}</span><span class="s2">)&quot;</span>
<span class="k">def</span> <span class="fm">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)):</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">return</span> <span class="nb">all</span><span class="p">(</span>
<span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="o">==</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"_db"</span><span class="p">,</span> <span class="s2">"_pk"</span><span class="p">]</span>
<span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="o">==</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">&quot;_db&quot;</span><span class="p">,</span> <span class="s2">&quot;_pk&quot;</span><span class="p">]</span>
<span class="p">)</span>
<span class="k">def</span> <span class="fm">__ne__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
@@ -625,7 +658,7 @@
<span class="k">def</span> <span class="nf">rotate_image_point</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">xmid</span><span class="p">,</span> <span class="n">ymid</span><span class="p">,</span> <span class="n">angle</span><span class="p">):</span>
<span class="sd">"""rotate image point about xm, ym by angle in radians</span>
<span class="sd">&quot;&quot;&quot;rotate image point about xm, ym by angle in radians</span>
<span class="sd"> Arguments:</span>
<span class="sd"> x: x coordinate of point to rotate</span>
@@ -637,7 +670,7 @@
<span class="sd"> Returns:</span>
<span class="sd"> tuple of rotated points (xr, yr)</span>
<span class="sd"> """</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="c1"># translate point relative to the mid point</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">x</span> <span class="o">-</span> <span class="n">xmid</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">y</span> <span class="o">-</span> <span class="n">ymid</span>
@@ -688,7 +721,9 @@
</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/_sphinx_javascript_frameworks_compat.js"></script>
<script src="../../_static/doctools.js"></script>
<script src="../../_static/sphinx_highlight.js"></script>
<script src="../../_static/scripts/furo.js"></script>
<script src="../../_static/clipboard.min.js"></script>
<script src="../../_static/copybutton.js"></script>

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-5.3.0, furo 2022.09.29"/>
<title>osxphotos.photoinfo - osxphotos 0.56.4 documentation</title>
<title>osxphotos.photoinfo - osxphotos 0.56.5 documentation</title>
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<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.56.4 documentation</div></a>
<a href="../../index.html"><div class="brand">osxphotos 0.56.5 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -146,7 +146,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
<span class="sidebar-brand-text">osxphotos 0.56.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.5 documentation</span>
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
@@ -195,9 +195,7 @@
</div>
<article role="main">
<h1>Source code for osxphotos.photoinfo</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">PhotoInfo class</span>
<span class="sd">Represents a single photo in the Photos library and provides access to the photo&#39;s attributes</span>
<span></span><span class="sd">&quot;&quot;&quot; PhotoInfo class: Represents a single photo in the Photos library and provides access to the photo&#39;s attributes</span>
<span class="sd">PhotosDB.photos() returns a list of PhotoInfo objects</span>
<span class="sd">&quot;&quot;&quot;</span>
@@ -214,11 +212,13 @@
<span class="kn">import</span> <span class="nn">plistlib</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">Dict</span><span class="p">,</span> <span class="n">Optional</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Any</span><span class="p">,</span> <span class="n">Dict</span><span class="p">,</span> <span class="n">Optional</span>
<span class="kn">import</span> <span class="nn">yaml</span>
<span class="kn">from</span> <span class="nn">osxmetadata</span> <span class="kn">import</span> <span class="n">OSXMetaData</span>
<span class="kn">import</span> <span class="nn">osxphotos</span>
<span class="kn">from</span> <span class="nn">._constants</span> <span class="kn">import</span> <span class="p">(</span>
<span class="n">_DB_TABLE_NAMES</span><span class="p">,</span>
<span class="n">_MOVIE_TYPE</span><span class="p">,</span>
@@ -272,10 +272,10 @@
<span class="sd"> including keywords, persons, albums, uuid, path, etc.</span>
<span class="sd"> &quot;&quot;&quot;</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="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">uuid</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">info</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">_uuid</span> <span class="o">=</span> <span class="n">uuid</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_info</span> <span class="o">=</span> <span class="n">info</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="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="s2">&quot;osxphotos.PhotosDB&quot;</span><span class="p">,</span> <span class="n">uuid</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">info</span><span class="p">:</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">]):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_uuid</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="n">uuid</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_info</span><span class="p">:</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">]</span> <span class="o">=</span> <span class="n">info</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="p">:</span> <span class="s2">&quot;osxphotos.PhotosDB&quot;</span> <span class="o">=</span> <span class="n">db</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_verbose</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">_verbose</span>
<span class="nd">@property</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-5.3.0, furo 2022.09.29"/>
<title>osxphotos.photosdb.photosdb - osxphotos 0.56.4 documentation</title>
<title>osxphotos.photosdb.photosdb - osxphotos 0.56.5 documentation</title>
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<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.56.4 documentation</div></a>
<a href="../../../index.html"><div class="brand">osxphotos 0.56.5 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -146,7 +146,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../../index.html">
<span class="sidebar-brand-text">osxphotos 0.56.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.5 documentation</span>
</a><form class="sidebar-search-container" method="get" action="../../../search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
@@ -200,18 +200,21 @@
<span class="sd">Processes a Photos.app library database to extract information about photos</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">annotations</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">os.path</span>
<span class="kn">import</span> <span class="nn">pathlib</span>
<span class="kn">import</span> <span class="nn">platform</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">sqlite3</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">tempfile</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">OrderedDict</span>
<span class="kn">from</span> <span class="nn">collections.abc</span> <span class="kn">import</span> <span class="n">Iterable</span>
<span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span><span class="p">,</span> <span class="n">timedelta</span><span class="p">,</span> <span class="n">timezone</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Optional</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Any</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">Optional</span>
<span class="kn">from</span> <span class="nn">unicodedata</span> <span class="kn">import</span> <span class="n">normalize</span>
<span class="kn">import</span> <span class="nn">bitmath</span>
@@ -902,6 +905,8 @@
<span class="s2">&quot;displayname&quot;</span><span class="p">:</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">person</span><span class="p">[</span><span class="mi">4</span><span class="p">]),</span>
<span class="s2">&quot;photo_uuid&quot;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
<span class="s2">&quot;keyface_uuid&quot;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
<span class="s2">&quot;type&quot;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="c1"># Photos 5+</span>
<span class="s2">&quot;manualorder&quot;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="c1"># Photos 5+</span>
<span class="p">}</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_fullname</span><span class="p">[</span><span class="n">fullname</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pk</span><span class="p">)</span>
@@ -1884,7 +1889,9 @@
<span class="sd"> ZPERSON.ZFULLNAME,</span>
<span class="sd"> ZPERSON.ZFACECOUNT,</span>
<span class="sd"> ZPERSON.ZKEYFACE,</span>
<span class="sd"> ZPERSON.ZDISPLAYNAME</span>
<span class="sd"> ZPERSON.ZDISPLAYNAME,</span>
<span class="sd"> ZPERSON.ZTYPE,</span>
<span class="sd"> ZPERSON.ZMANUALORDER</span>
<span class="sd"> FROM ZPERSON</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="p">)</span>
@@ -1895,6 +1902,8 @@
<span class="c1"># 3 ZPERSON.ZFACECOUNT,</span>
<span class="c1"># 4 ZPERSON.ZKEYFACE,</span>
<span class="c1"># 5 ZPERSON.ZDISPLAYNAME</span>
<span class="c1"># 6 ZPERSON.ZTYPE, # ZTYPE = 1 == favorite, 0 == not favorite</span>
<span class="c1"># 7 ZPERSON.ZMANUALORDER # favorites are sorted by ZMANUALORDER</span>
<span class="k">for</span> <span class="n">person</span> <span class="ow">in</span> <span class="n">c</span><span class="p">:</span>
<span class="n">pk</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
@@ -1912,6 +1921,8 @@
<span class="s2">&quot;displayname&quot;</span><span class="p">:</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">person</span><span class="p">[</span><span class="mi">5</span><span class="p">]),</span>
<span class="s2">&quot;photo_uuid&quot;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
<span class="s2">&quot;keyface_uuid&quot;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
<span class="s2">&quot;type&quot;</span><span class="p">:</span> <span class="n">person</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span>
<span class="s2">&quot;manualorder&quot;</span><span class="p">:</span> <span class="n">person</span><span class="p">[</span><span class="mi">7</span><span class="p">],</span>
<span class="p">}</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_fullname</span><span class="p">[</span><span class="n">fullname</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pk</span><span class="p">)</span>
@@ -3760,10 +3771,11 @@
<span class="k">return</span> <span class="n">photos</span></div>
<div class="viewcode-block" id="PhotosDB.execute"><a class="viewcode-back" href="../../../reference.html#osxphotos.PhotosDB.execute">[docs]</a> <span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sql</span><span class="p">):</span>
<div class="viewcode-block" id="PhotosDB.execute"><a class="viewcode-back" href="../../../reference.html#osxphotos.PhotosDB.execute">[docs]</a> <span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">params</span><span class="p">:</span> <span class="n">Any</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">Cursor</span><span class="p">:</span>
<span class="sd">&quot;&quot;&quot;Execute sql statement and return cursor&quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_db_connection</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_db_connection</span><span class="p">()</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db_connection</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">sql</span><span class="p">)</span></div>
<span class="n">params</span> <span class="o">=</span> <span class="n">params</span> <span class="ow">or</span> <span class="p">()</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db_connection</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">params</span><span class="p">)</span></div>
<span class="k">def</span> <span class="nf">_duplicate_signature</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">uuid</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Compute a signature for finding possible duplicates&quot;&quot;&quot;</span>

View File

@@ -357,7 +357,7 @@ Template Substitutions
* - {tab}
- :A tab: '\t'
* - {osxphotos_version}
- The osxphotos version, e.g. '0.56.4'
- The osxphotos version, e.g. '0.56.6'
* - {osxphotos_cmd_line}
- The full command line used to run osxphotos
* - {album}

View File

@@ -1,6 +1,6 @@
var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '0.56.4',
VERSION: '0.56.6',
LANGUAGE: 'en',
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-5.3.0, furo 2022.09.29"/>
<title>OSXPhotos Command Line Interface (CLI) - osxphotos 0.56.4 documentation</title>
<title>OSXPhotos Command Line Interface (CLI) - osxphotos 0.56.6 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<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.56.4 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.56.6 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -147,7 +147,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
<span class="sidebar-brand-text">osxphotos 0.56.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.6 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
@@ -4404,6 +4404,12 @@ See Timewarp Overview below for additional information.</p>
<dd><p>Pull date/time and timezone for selected photos from EXIF metadata in the original file into Photos and update the associated data in Photos to match the EXIF data. pull-exif will be executed before any other updates are performed on the photo. It is possible for images to have missing EXIF data, for example the date/time could be set but there might be no timezone set in the EXIF metadata. Missing data will be handled thusly: if date/time/timezone are all present in the EXIF data, the photos date/time/timezone will be updated. If timezone is missing but date/time is present, only the photos date/time will be updated. If date/time is missing but the timezone is present, only the photos timezone will be updated unless use-file-time is set in which case, the photos file modification date/time will be used in place of EXIF date/time. If the date is present but the time is missing, the time will be set to 00:00:00. Requires the third-party exiftool utility be installed (see <a class="reference external" href="https://exiftool.org/">https://exiftool.org/</a>). See also push-exif.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-timewarp-M">
<span id="cmdoption-osxphotos-timewarp-m"></span><span id="cmdoption-osxphotos-timewarp-parse-date"></span><span class="sig-name descname"><span class="pre">-M</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--parse-date</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;DATE_PATTERN&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-timewarp-M" title="Permalink to this definition">#</a></dt>
<dd><p>Parse date from filename using DATE_PATTERN and set photos date to match. If file does not match DATE_PATTERN, the date will not be changed. DATE_PATTERN is a strptime-compatible pattern with extensions as pattern described below. If DATE_PATTERN matches time zone information, the photos timezone will be set to match. For example, if your photos are named IMG_1234_2022_11_23_12_34_56.jpg where the date/time is 2022-11-23 12:34:56, you could use the pattern %Y_%m_%d_%H_%M_%S or IMG_*_%Y_%m_%d_%H_%M_%S to further narrow the pattern to only match files with <a href="#id5"><span class="problematic" id="id6">IMG_xxxx_</span></a> in the name.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-timewarp-F">
<span id="cmdoption-osxphotos-timewarp-f"></span><span id="cmdoption-osxphotos-timewarp-function"></span><span class="sig-name descname"><span class="pre">-F</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--function</span></span><span class="sig-prename descclassname"> <span class="pre">&lt;filename.py::function&gt;</span></span><a class="headerlink" href="#cmdoption-osxphotos-timewarp-F" title="Permalink to this definition">#</a></dt>
@@ -4411,14 +4417,14 @@ See Timewarp Overview below for additional information.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-timewarp-m">
<span id="cmdoption-osxphotos-timewarp-match-time"></span><span class="sig-name descname"><span class="pre">-m</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--match-time</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-timewarp-m" title="Permalink to this definition">#</a></dt>
<dt class="sig sig-object std" id="cmdoption-osxphotos-timewarp-0">
<span id="cmdoption-osxphotos-timewarp-match-time"></span><span class="sig-name descname"><span class="pre">-m</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--match-time</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-timewarp-0" title="Permalink to this definition">#</a></dt>
<dd><p>When used with timezone, adjusts the photo time so that the timestamp in the new timezone matches the timestamp in the old timezone. For example, if photo has time of 12:00 and timezone of GMT+01:00 and new timezone is specified as timezone +02:00 (one hour ahead of current GMT+01:00 timezone), the photos new time will be 12:00 GMT+02:00. That is, the timezone will have changed but the timestamp of the photo will match the previous timestamp. Use match-time when the cameras time was correct for the time the photo was taken but the timezone was missing or wrong and you want to adjust the timezone while preserving the photos time. See also timezone.</p>
</dd></dl>
<dl class="std option">
<dt class="sig sig-object std" id="cmdoption-osxphotos-timewarp-0">
<span id="cmdoption-osxphotos-timewarp-use-file-time"></span><span class="sig-name descname"><span class="pre">-f</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--use-file-time</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-timewarp-0" title="Permalink to this definition">#</a></dt>
<dt class="sig sig-object std" id="cmdoption-osxphotos-timewarp-1">
<span id="cmdoption-osxphotos-timewarp-use-file-time"></span><span class="sig-name descname"><span class="pre">-f</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--use-file-time</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-timewarp-1" title="Permalink to this definition">#</a></dt>
<dd><p>When used with pull-exif, the file modification date/time will be used if date/time is missing from the EXIF data.</p>
</dd></dl>

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-5.3.0, furo 2022.09.29"/><title>Index - osxphotos 0.56.4 documentation</title>
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Index - osxphotos 0.56.6 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<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.56.4 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.56.6 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -145,7 +145,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
<span class="sidebar-brand-text">osxphotos 0.56.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.6 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
@@ -1264,7 +1264,7 @@
--match-time
<ul>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-m">osxphotos-timewarp command line option</a>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-0">osxphotos-timewarp command line option</a>
</li>
</ul></li>
<li>
@@ -1797,6 +1797,8 @@
<ul>
<li><a href="cli.html#cmdoption-osxphotos-import-P">osxphotos-import command line option</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-M">osxphotos-timewarp command line option</a>
</li>
</ul></li>
<li>
@@ -2411,7 +2413,7 @@
--use-file-time
<ul>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-0">osxphotos-timewarp command line option</a>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-1">osxphotos-timewarp command line option</a>
</li>
</ul></li>
<li>
@@ -2645,7 +2647,7 @@
</li>
<li><a href="cli.html#cmdoption-osxphotos-query-f">osxphotos-query command line option</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-0">osxphotos-timewarp command line option</a>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-1">osxphotos-timewarp command line option</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-uuid-f">osxphotos-uuid command line option</a>
</li>
@@ -2702,6 +2704,13 @@
<ul>
<li><a href="cli.html#cmdoption-osxphotos-import-l">osxphotos-import command line option</a>
</li>
</ul></li>
<li>
-M
<ul>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-M">osxphotos-timewarp command line option</a>
</li>
</ul></li>
<li>
@@ -2712,7 +2721,7 @@
</li>
<li><a href="cli.html#cmdoption-osxphotos-sync-m">osxphotos-sync command line option</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-m">osxphotos-timewarp command line option</a>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-0">osxphotos-timewarp command line option</a>
</li>
</ul></li>
<li>
@@ -3172,13 +3181,17 @@
</ul></li>
<li><a href="reference.html#osxphotos.ExportOptions.face_regions">face_regions (osxphotos.ExportOptions attribute)</a>
</li>
<li><a href="reference.html#osxphotos.PhotoInfo.favorite">favorite (osxphotos.PhotoInfo property)</a>
<li><a href="reference.html#osxphotos.PersonInfo.favorite">favorite (osxphotos.PersonInfo property)</a>
<ul>
<li><a href="reference.html#osxphotos.PhotoInfo.favorite">(osxphotos.PhotoInfo property)</a>
</li>
<li><a href="reference.html#osxphotos.QueryOptions.favorite">(osxphotos.QueryOptions attribute)</a>
</li>
</ul></li>
<li><a href="reference.html#osxphotos.ExportOptions.favorite_rating">favorite_rating (osxphotos.ExportOptions attribute)</a>
</li>
<li><a href="reference.html#osxphotos.PersonInfo.feature_less">feature_less (osxphotos.PersonInfo property)</a>
</li>
<li><a href="reference.html#osxphotos.FileUtilNoOp.file_sig">file_sig() (osxphotos.FileUtilNoOp class method)</a>
</li>
@@ -3192,11 +3205,11 @@
</li>
</ul></li>
<li><a href="reference.html#osxphotos.FileUtil">FileUtil (class in osxphotos)</a>
</li>
<li><a href="reference.html#osxphotos.ExportOptions.fileutil">fileutil (osxphotos.ExportOptions attribute)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#osxphotos.ExportOptions.fileutil">fileutil (osxphotos.ExportOptions attribute)</a>
</li>
<li><a href="reference.html#osxphotos.FileUtilNoOp">FileUtilNoOp (class in osxphotos)</a>
</li>
<li><a href="reference.html#osxphotos.PhotoTemplate.filter_predicate">filter_predicate() (osxphotos.PhotoTemplate method)</a>
@@ -5096,9 +5109,11 @@
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-L">--library</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-m">--match-time</a>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-0">--match-time</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-o">--output-file</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-M">--parse-date</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-plain">--plain</a>
</li>
@@ -5116,7 +5131,7 @@
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-z">--timezone</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-0">--use-file-time</a>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-1">--use-file-time</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-V">--verbose</a>
</li>
@@ -5132,13 +5147,15 @@
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-F">-F</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-0">-f</a>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-1">-f</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-i">-i</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-L">-L</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-m">-m</a>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-M">-M</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-0">-m</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-timewarp-o">-o</a>
</li>
@@ -5446,14 +5463,14 @@
</li>
<li><a href="reference.html#osxphotos.ExifTool.setvalue">setvalue() (osxphotos.ExifTool method)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#osxphotos.PhotoInfo.shared">shared (osxphotos.PhotoInfo property)</a>
<ul>
<li><a href="reference.html#osxphotos.QueryOptions.shared">(osxphotos.QueryOptions attribute)</a>
</li>
</ul></li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#osxphotos.ExportOptions.sidecar">sidecar (osxphotos.ExportOptions attribute)</a>
</li>
<li><a href="reference.html#osxphotos.ExportOptions.sidecar_drop_ext">sidecar_drop_ext (osxphotos.ExportOptions attribute)</a>
@@ -5465,7 +5482,11 @@
</li>
</ul></li>
<li><a href="reference.html#osxphotos.AlbumInfo.sort_order">sort_order (osxphotos.AlbumInfo property)</a>
<ul>
<li><a href="reference.html#osxphotos.PersonInfo.sort_order">(osxphotos.PersonInfo property)</a>
</li>
</ul></li>
<li><a href="reference.html#osxphotos.SearchInfo.source">source (osxphotos.SearchInfo property)</a>
</li>
<li><a href="reference.html#osxphotos.MomentInfo.start_date">start_date (osxphotos.MomentInfo property)</a>

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-5.3.0, furo 2022.09.29"/>
<title>osxphotos 0.56.4 documentation</title>
<title>osxphotos 0.56.6 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<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.56.4 documentation</div></a>
<a href="#"><div class="brand">osxphotos 0.56.6 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -147,7 +147,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="#">
<span class="sidebar-brand-text">osxphotos 0.56.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.6 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
@@ -422,8 +422,11 @@
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.PersonInfo"><code class="docutils literal notranslate"><span class="pre">PersonInfo</span></code></a><ul>
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.asdict"><code class="docutils literal notranslate"><span class="pre">PersonInfo.asdict()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.face_info"><code class="docutils literal notranslate"><span class="pre">PersonInfo.face_info</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.favorite"><code class="docutils literal notranslate"><span class="pre">PersonInfo.favorite</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.feature_less"><code class="docutils literal notranslate"><span class="pre">PersonInfo.feature_less</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.json"><code class="docutils literal notranslate"><span class="pre">PersonInfo.json()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.photos"><code class="docutils literal notranslate"><span class="pre">PersonInfo.photos</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.sort_order"><code class="docutils literal notranslate"><span class="pre">PersonInfo.sort_order</span></code></a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.PhotoExporter"><code class="docutils literal notranslate"><span class="pre">PhotoExporter</span></code></a><ul>

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-5.3.0, furo 2022.09.29"/>
<title>OSXPhotos - osxphotos 0.56.4 documentation</title>
<title>OSXPhotos - osxphotos 0.56.6 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<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.56.4 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.56.6 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -147,7 +147,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
<span class="sidebar-brand-text">osxphotos 0.56.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.6 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">

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-5.3.0, furo 2022.09.29"/>
<title>OSXPhotos Python Package Overview - osxphotos 0.56.4 documentation</title>
<title>OSXPhotos Python Package Overview - osxphotos 0.56.6 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<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.56.4 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.56.6 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -147,7 +147,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
<span class="sidebar-brand-text">osxphotos 0.56.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.6 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">

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-5.3.0, furo 2022.09.29"/><title>Python Module Index - osxphotos 0.56.4 documentation</title>
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Python Module Index - osxphotos 0.56.6 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<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.56.4 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.56.6 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -145,7 +145,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
<span class="sidebar-brand-text">osxphotos 0.56.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.6 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">

View File

@@ -6,7 +6,7 @@
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="prev" title="OSXPhotos Python Package Overview" href="package_overview.html" />
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
<title>OSXPhotos python API - osxphotos 0.56.4 documentation</title>
<title>OSXPhotos python API - osxphotos 0.56.6 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<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.56.4 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.56.6 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -147,7 +147,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
<span class="sidebar-brand-text">osxphotos 0.56.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.6 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
@@ -1295,7 +1295,7 @@ including folders, albums, etc</p>
<dl class="py class">
<dt class="sig sig-object py" id="osxphotos.PersonInfo">
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">osxphotos.</span></span><span class="sig-name descname"><span class="pre">PersonInfo</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">db</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">pk</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/osxphotos/personinfo.html#PersonInfo"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PersonInfo" title="Permalink to this definition">#</a></dt>
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">osxphotos.</span></span><span class="sig-name descname"><span class="pre">PersonInfo</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">db</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#osxphotos.PhotosDB" title="osxphotos.photosdb.photosdb.PhotosDB"><span class="pre">PhotosDB</span></a></span></em>, <em class="sig-param"><span class="n"><span class="pre">pk</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">int</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/osxphotos/personinfo.html#PersonInfo"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PersonInfo" title="Permalink to this definition">#</a></dt>
<dd><p>Info about a person in the Photos library</p>
<dl class="py method">
<dt class="sig sig-object py" id="osxphotos.PersonInfo.asdict">
@@ -1310,6 +1310,18 @@ including folders, albums, etc</p>
Highest quality face is result[0] and lowest quality face is result[n]</p>
</dd></dl>
<dl class="py property">
<dt class="sig sig-object py" id="osxphotos.PersonInfo.favorite">
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">favorite</span></span><a class="headerlink" href="#osxphotos.PersonInfo.favorite" title="Permalink to this definition">#</a></dt>
<dd><p>Returns True if person is a favorite, False otherwise; Photos 5+ only; returns False on Photos &lt;= 4</p>
</dd></dl>
<dl class="py property">
<dt class="sig sig-object py" id="osxphotos.PersonInfo.feature_less">
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">feature_less</span></span><a class="headerlink" href="#osxphotos.PersonInfo.feature_less" title="Permalink to this definition">#</a></dt>
<dd><p>Returns True if person has been marked as “Feature This Person Less” in Photos, False otherwise; Photos 8+ only; returns False on Photos &lt;= 7</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="osxphotos.PersonInfo.json">
<span class="sig-name descname"><span class="pre">json</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="reference internal" href="_modules/osxphotos/personinfo.html#PersonInfo.json"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PersonInfo.json" title="Permalink to this definition">#</a></dt>
@@ -1322,6 +1334,12 @@ Highest quality face is result[0] and lowest quality face is result[n]</p>
<dd><p>Returns list of PhotoInfo objects associated with this person</p>
</dd></dl>
<dl class="py property">
<dt class="sig sig-object py" id="osxphotos.PersonInfo.sort_order">
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">sort_order</span></span><a class="headerlink" href="#osxphotos.PersonInfo.sort_order" title="Permalink to this definition">#</a></dt>
<dd><p>Returns sort order of person; favorite persons are sorted before non-favorite persons”; Photos 5+ only; returns 0 on Photos &lt;= 4</p>
</dd></dl>
</dd></dl>
<dl class="py class">
@@ -1420,7 +1438,7 @@ network drive or other slower external storage).</p>
<dl class="py class">
<dt class="sig sig-object py" id="osxphotos.PhotoInfo">
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">osxphotos.</span></span><span class="sig-name descname"><span class="pre">PhotoInfo</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">db</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">uuid</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">info</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/osxphotos/photoinfo.html#PhotoInfo"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotoInfo" title="Permalink to this definition">#</a></dt>
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">osxphotos.</span></span><span class="sig-name descname"><span class="pre">PhotoInfo</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">db</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#osxphotos.PhotosDB" title="osxphotos.photosdb.photosdb.PhotosDB"><span class="pre">PhotosDB</span></a></span></em>, <em class="sig-param"><span class="n"><span class="pre">uuid</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">str</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">info</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">dict</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">Any</span><span class="p"><span class="pre">]</span></span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/osxphotos/photoinfo.html#PhotoInfo"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotoInfo" title="Permalink to this definition">#</a></dt>
<dd><p>Info about a specific photo, contains all the details about the photo
including keywords, persons, albums, uuid, path, etc.</p>
<dl class="py property">
@@ -2314,7 +2332,7 @@ valid only on Photos 5; on Photos &lt;= 4, prints warning and returns empty dict
<dl class="py method">
<dt class="sig sig-object py" id="osxphotos.PhotosDB.execute">
<span class="sig-name descname"><span class="pre">execute</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">sql</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/osxphotos/photosdb/photosdb.html#PhotosDB.execute"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotosDB.execute" title="Permalink to this definition">#</a></dt>
<span class="sig-name descname"><span class="pre">execute</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">sql</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">str</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">params</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Any</span><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><span class="pre">None</span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">Cursor</span></span></span><a class="reference internal" href="_modules/osxphotos/photosdb/photosdb.html#PhotosDB.execute"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotosDB.execute" title="Permalink to this definition">#</a></dt>
<dd><p>Execute sql statement and return cursor</p>
</dd></dl>
@@ -3761,8 +3779,11 @@ Projects are cards, calendars, slideshows, etc.</p>
<li><a class="reference internal" href="#osxphotos.PersonInfo"><code class="docutils literal notranslate"><span class="pre">PersonInfo</span></code></a><ul>
<li><a class="reference internal" href="#osxphotos.PersonInfo.asdict"><code class="docutils literal notranslate"><span class="pre">PersonInfo.asdict()</span></code></a></li>
<li><a class="reference internal" href="#osxphotos.PersonInfo.face_info"><code class="docutils literal notranslate"><span class="pre">PersonInfo.face_info</span></code></a></li>
<li><a class="reference internal" href="#osxphotos.PersonInfo.favorite"><code class="docutils literal notranslate"><span class="pre">PersonInfo.favorite</span></code></a></li>
<li><a class="reference internal" href="#osxphotos.PersonInfo.feature_less"><code class="docutils literal notranslate"><span class="pre">PersonInfo.feature_less</span></code></a></li>
<li><a class="reference internal" href="#osxphotos.PersonInfo.json"><code class="docutils literal notranslate"><span class="pre">PersonInfo.json()</span></code></a></li>
<li><a class="reference internal" href="#osxphotos.PersonInfo.photos"><code class="docutils literal notranslate"><span class="pre">PersonInfo.photos</span></code></a></li>
<li><a class="reference internal" href="#osxphotos.PersonInfo.sort_order"><code class="docutils literal notranslate"><span class="pre">PersonInfo.sort_order</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#osxphotos.PhotoExporter"><code class="docutils literal notranslate"><span class="pre">PhotoExporter</span></code></a><ul>

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-5.3.0, furo 2022.09.29"/><title>Search - osxphotos 0.56.4 documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Search - osxphotos 0.56.6 documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<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.56.4 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.56.6 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -144,7 +144,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
<span class="sidebar-brand-text">osxphotos 0.56.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.6 documentation</span>
</a><form class="sidebar-search-container" method="get" action="#" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">

File diff suppressed because one or more lines are too long

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-5.3.0, furo 2022.09.29"/>
<title>OSXPhotos Template System - osxphotos 0.56.4 documentation</title>
<title>OSXPhotos Template System - osxphotos 0.56.6 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<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.56.4 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.56.6 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -147,7 +147,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
<span class="sidebar-brand-text">osxphotos 0.56.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.6 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
@@ -608,7 +608,7 @@
</td>
</tr>
<tr class="row-even"><td><p>{osxphotos_version}</p></td>
<td><p>The osxphotos version, e.g. 0.56.4</p></td>
<td><p>The osxphotos version, e.g. 0.56.6</p></td>
</tr>
<tr class="row-odd"><td><p>{osxphotos_cmd_line}</p></td>
<td><p>The full command line used to run osxphotos</p></td>

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-5.3.0, furo 2022.09.29"/>
<title>OSXPhotos Tutorial - osxphotos 0.56.4 documentation</title>
<title>OSXPhotos Tutorial - osxphotos 0.56.6 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
<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.56.4 documentation</div></a>
<a href="index.html"><div class="brand">osxphotos 0.56.6 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -147,7 +147,7 @@
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
<span class="sidebar-brand-text">osxphotos 0.56.4 documentation</span>
<span class="sidebar-brand-text">osxphotos 0.56.6 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">

View File

@@ -357,7 +357,7 @@ Template Substitutions
* - {tab}
- :A tab: '\t'
* - {osxphotos_version}
- The osxphotos version, e.g. '0.56.4'
- The osxphotos version, e.g. '0.56.6'
* - {osxphotos_cmd_line}
- The full command line used to run osxphotos
* - {album}

View File

@@ -1,3 +1,3 @@
""" version info """
__version__ = "0.56.4"
__version__ = "0.56.6"

View File

@@ -1,14 +1,13 @@
""" Fix time / date / timezone for photos in Apple Photos """
import datetime
import os
from __future__ import annotations
import sys
from functools import partial
from textwrap import dedent
from typing import Callable, Optional
import click
from photoscript import Photo, PhotosLibrary
from photoscript import PhotosLibrary
from rich.console import Console
from osxphotos._constants import APP_NAME
@@ -16,10 +15,14 @@ from osxphotos.compare_exif import PhotoCompare
from osxphotos.datetime_utils import datetime_naive_to_local, datetime_to_new_tz
from osxphotos.exif_datetime_updater import ExifDateTimeUpdater
from osxphotos.exiftool import get_exiftool_path
from osxphotos.photodates import (
set_photo_date_from_filename,
update_photo_date_time,
update_photo_from_function,
update_photo_time_for_new_timezone,
)
from osxphotos.photosalbum import PhotosAlbumPhotoScript
from osxphotos.phototz import PhotoTimeZone, PhotoTimeZoneUpdater
from osxphotos.timeutils import update_datetime
from osxphotos.timezones import Timezone
from osxphotos.utils import noop, pluralize
from .click_rich_echo import (
@@ -38,6 +41,7 @@ from .param_types import (
DateOffset,
DateTimeISO8601,
FunctionCall,
StrpDateTimePattern,
TimeOffset,
TimeString,
UTCOffset,
@@ -49,110 +53,6 @@ from .verbose import get_verbose_console, verbose_print
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S%z"
def update_photo_date_time(
photo: Photo,
date,
time,
date_delta,
time_delta,
verbose_print: Callable,
):
"""Update date, time in photo"""
photo_date = photo.date
new_photo_date = update_datetime(
photo_date, date=date, time=time, date_delta=date_delta, time_delta=time_delta
)
filename = photo.filename
uuid = photo.uuid
if new_photo_date != photo_date:
photo.date = new_photo_date
verbose_print(
f"Updated date/time for photo [filename]{filename}[/filename] "
f"([uuid]{uuid}[/uuid]) from: [time]{photo_date}[/time] to [time]{new_photo_date}[/time]"
)
else:
verbose_print(
f"Skipped date/time update for photo [filename]{filename}[/filename] "
f"([uuid]{uuid}[/uuid]): nothing to do"
)
def update_photo_time_for_new_timezone(
library_path: str,
photo: Photo,
new_timezone: Timezone,
verbose_print: Callable,
):
"""Update time in photo to keep it the same time but in a new timezone
For example, photo time is 12:00+0100 and new timezone is +0200,
so adjust photo time by 1 hour so it will now be 12:00+0200 instead of
13:00+0200 as it would be with no adjustment to the time"""
old_timezone = PhotoTimeZone(library_path=library_path).get_timezone(photo)[0]
# need to move time in opposite direction of timezone offset so that
# photo time is the same time but in the new timezone
delta = old_timezone - new_timezone.offset
photo_date = photo.date
new_photo_date = update_datetime(
dt=photo_date, time_delta=datetime.timedelta(seconds=delta)
)
filename = photo.filename
uuid = photo.uuid
if photo_date != new_photo_date:
photo.date = new_photo_date
verbose_print(
f"Adjusted date/time for photo [filename]{filename}[/filename] ([uuid]{uuid}[/uuid]) to match "
f"previous time [time]{photo_date}[time] but in new timezone [tz]{new_timezone}[/tz]."
)
else:
verbose_print(
f"Skipping date/time update for photo [filename]{filename}[/filename] ([uuid]{photo.uuid}[/uuid]), "
f"already matches new timezone [tz]{new_timezone}[/tz]"
)
def update_photo_from_function(
library_path: str,
function: Callable,
verbose_print: Callable,
photo: Photo,
path: Optional[str],
):
"""Update photo from function call"""
photo_tz_sec, _, photo_tz_name = PhotoTimeZone(
library_path=library_path
).get_timezone(photo)
dt_new, tz_new = function(
photo=photo,
path=path,
tz_sec=photo_tz_sec,
tz_name=photo_tz_name,
verbose=verbose_print,
)
if dt_new != photo.date:
old_date = photo.date
photo.date = dt_new
verbose_print(
f"Updated date/time for photo [filename]{photo.filename}[/filename] "
f"([uuid]{photo.uuid}[/uuid]) from: [time]{old_date}[/time] to [time]{dt_new}[/time]"
)
else:
verbose_print(
f"Skipped date/time update for photo [filename]{photo.filename}[/filename] "
f"([uuid]{photo.uuid}[/uuid]): nothing to do"
)
if tz_new != photo_tz_sec:
tz_updater = PhotoTimeZoneUpdater(
timezone=Timezone(tz_new), verbose=verbose_print, library_path=library_path
)
tz_updater.update_photo(photo)
else:
verbose_print(
f"Skipped timezone update for photo [filename]{photo.filename}[/filename] "
f"([uuid]{photo.uuid}[/uuid]): nothing to do"
)
class TimeWarpCommand(click.Command):
"""Custom click.Command that overrides get_help() to show additional help info for export"""
@@ -223,6 +123,40 @@ if the EXIF data is missing, use the file modification date/time; show verbose o
`osxphotos timewarp --pull-exif --use-file-time --verbose`
## Parsing Dates/Times from Filenames
The --parse-date option allows you to parse dates/times from the original filename of the photo.
This is useful if you files with dates/times embedded in the filename but not in the metadata.
The argument to `--parse-date` is a pattern string that is used to parse the date/time
from the filename. The pattern string is a superset of the python `strftime/strptime`
format with the following additions:
- *: Match any number of characters
- ^: Match the beginning of the string
- $: Match the end of the string
- {n}: Match exactly n characters
- {n,}: Match at least n characters
- {n,m}: Match at least n characters and at most m characters
- In addition to `%%` for a literal `%`, the following format codes are supported:
`%^`, `%$`, `%*`, `%|`, `%{`, `%}` for `^`, `$`, `*`, `|`, `{`, `}` respectively
- |: join multiple format codes; each code is tried in order until one matches
- Unlike the standard library, the leading zero is not optional for
%d, %m, %H, %I, %M, %S, %j, %U, %W, and %V
- For optional leading zero, use %-d, %-m, %-H, %-I, %-M, %-S, %-j, %-U, %-W, and %-V
For more information on strptime format codes, see:
https://docs.python.org/3/library/datetime.html?highlight=strptime#strftime-and-strptime-format-codes
**Note**: The time zone of the parsed date/time is assumed to be the local time zone.
If the parse pattern includes a time zone, the photo's time will be converted from
the specified time zone to the local time zone. osxphotos import does not
currently support setting the time zone of imported photos.
See also `osxphotos help timewarp` for more information on the timewarp
command which can be used to change the time zone of photos after import.
"""
),
width=formatter.width,
@@ -322,6 +256,19 @@ if the EXIF data is missing, use the file modification date/time; show verbose o
"Requires the third-party exiftool utility be installed (see https://exiftool.org/). "
"See also --push-exif.",
)
@click.option(
"--parse-date",
"-M",
metavar="DATE_PATTERN",
type=StrpDateTimePattern(),
help="Parse date from filename using DATE_PATTERN and set photo's date to match. "
"If file does not match DATE_PATTERN, the date will not be changed. "
"DATE_PATTERN is a strptime-compatible pattern with extensions as pattern described below. "
"If DATE_PATTERN matches time zone information, the photo's timezone will be set to match. "
"For example, if your photos are named 'IMG_1234_2022_11_23_12_34_56.jpg' where the date/time is "
"'2022-11-23 12:34:56', you could use the pattern '%Y_%m_%d_%H_%M_%S' or "
"'IMG_*_%Y_%m_%d_%H_%M_%S' to further narrow the pattern to only match files with 'IMG_xxxx_' in the name.",
)
@click.option(
"--function",
"-F",
@@ -363,7 +310,7 @@ if the EXIF data is missing, use the file modification date/time; show verbose o
help="When used with --compare-exif, adds any photos with date/time/timezone differences "
"between Photos/EXIF to album ALBUM. If ALBUM does not exist, it will be created.",
)
@click.option("--verbose", "-V", "verbose", is_flag=True, help="Show verbose output.")
@click.option("--verbose", "-V", "verbose_", is_flag=True, help="Show verbose output.")
@click.option(
"--library",
"-L",
@@ -419,9 +366,10 @@ def timewarp(
use_file_time,
add_to_album,
exiftool_path,
verbose,
verbose_,
library,
theme,
parse_date,
plain,
output_file,
terminal_width,
@@ -446,6 +394,7 @@ def timewarp(
timezone,
inspect,
compare_exif,
parse_date,
push_exif,
pull_exif,
function,
@@ -453,7 +402,8 @@ def timewarp(
):
raise click.UsageError(
"At least one of --date, --date-delta, --time, --time-delta, "
"--timezone, --inspect, --compare-exif, --push-exif, --pull-exif, --function "
"--timezone, --inspect, --compare-exif, --push-exif, --pull-exif, "
"--parse-date, --function "
"must be specified."
)
@@ -472,8 +422,8 @@ def timewarp(
# 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,
verbose = verbose_print(
verbose_,
timestamp,
rich=True,
theme=color_theme,
@@ -499,7 +449,7 @@ def timewarp(
if any([compare_exif, push_exif, pull_exif]):
exiftool_path = exiftool_path or get_exiftool_path()
verbose_(f"exiftool path: [filename]{exiftool_path}[/filename]")
verbose(f"exiftool path: [filename]{exiftool_path}[/filename]")
try:
photos = PhotosLibrary().selection
@@ -533,6 +483,7 @@ def timewarp(
push_exif,
pull_exif,
function,
parse_date,
]
)
and not force
@@ -556,13 +507,19 @@ def timewarp(
time=time,
date_delta=date_delta,
time_delta=time_delta,
verbose_print=verbose_,
verbose=verbose,
)
update_photo_time_for_new_timezone_ = partial(
update_photo_time_for_new_timezone,
library_path=library,
verbose_print=verbose_,
verbose=verbose,
)
set_photo_date_from_filename_ = partial(
set_photo_date_from_filename,
library_path=library,
verbose=verbose,
)
if function:
@@ -570,7 +527,7 @@ def timewarp(
update_photo_from_function,
library_path=library,
function=function[0],
verbose_print=verbose_,
verbose=verbose,
)
else:
update_photo_from_function_ = noop
@@ -579,14 +536,20 @@ def timewarp(
tzinfo = PhotoTimeZone(library_path=library)
if photos:
rich_echo(
"[filename]filename[/filename], [uuid]uuid[/uuid], [time]photo time (local)[/time], [time]photo time[/time], [tz]timezone offset[/tz], [tz]timezone name[/tz]"
"[filename]filename[/filename], [uuid]uuid[/uuid], "
"[time]photo time (local)[/time], "
"[time]photo time[/time], "
"[tz]timezone offset[/tz], [tz]timezone name[/tz]"
)
for photo in photos:
tz_seconds, tz_str, tz_name = tzinfo.get_timezone(photo)
photo_date_local = datetime_naive_to_local(photo.date)
photo_date_tz = datetime_to_new_tz(photo_date_local, tz_seconds)
rich_echo(
f"[filename]{photo.filename}[/filename], [uuid]{photo.uuid}[/uuid], [time]{photo_date_local.strftime(DATETIME_FORMAT)}[/time], [time]{photo_date_tz.strftime(DATETIME_FORMAT)}[/time], [tz]{tz_str}[/tz], [tz]{tz_name}[/tz]"
f"[filename]{photo.filename}[/filename], [uuid]{photo.uuid}[/uuid], "
f"[time]{photo_date_local.strftime(DATETIME_FORMAT)}[/time], "
f"[time]{photo_date_tz.strftime(DATETIME_FORMAT)}[/time], "
f"[tz]{tz_str}[/tz], [tz]{tz_name}[/tz]"
)
sys.exit(0)
@@ -596,7 +559,7 @@ def timewarp(
if photos:
photocomp = PhotoCompare(
library_path=library,
verbose=verbose_,
verbose=verbose,
exiftool_path=exiftool_path,
)
if not album:
@@ -622,12 +585,12 @@ def timewarp(
if album:
if diff_results.diff:
different_photos += 1
verbose_(
verbose(
f"Photo {filename} ({uuid}) has different date/time/timezone, adding to album '{album.name}'"
)
album.add(photo)
else:
verbose_(f"Photo {filename} ({uuid}) has same date/time/timezone")
verbose(f"Photo {filename} ({uuid}) has same date/time/timezone")
else:
rich_echo(
f"{filename}, {uuid}, "
@@ -644,14 +607,14 @@ def timewarp(
if timezone:
tz_updater = PhotoTimeZoneUpdater(
timezone, verbose=verbose_, library_path=library
timezone, verbose=verbose, library_path=library
)
if any([push_exif, pull_exif, function]):
# ExifDateTimeUpdater used to get photo path for --function
exif_updater = ExifDateTimeUpdater(
library_path=library,
verbose=verbose_,
verbose=verbose,
exiftool_path=exiftool_path,
plain=plain,
)
@@ -663,6 +626,8 @@ def timewarp(
total=num_photos,
)
for p in photos:
if parse_date:
set_photo_date_from_filename_(p, p.filename, parse_date)
if pull_exif:
exif_updater.update_photos_from_exif(
p, use_file_modify_date=use_file_time
@@ -676,7 +641,7 @@ def timewarp(
if timezone:
tz_updater.update_photo(p)
if function:
verbose_(f"Calling function [bold]{function[1]}")
verbose(f"Calling function [bold]{function[1]}")
photo_path = exif_updater.get_photo_path(p)
update_photo_from_function_(photo=p, path=photo_path)
if push_exif:

Binary file not shown.

View File

@@ -3,8 +3,10 @@
import json
import logging
import math
from collections import namedtuple
from functools import cached_property
import osxphotos
__all__ = ["PersonInfo", "FaceInfo", "rotate_image_point"]
@@ -15,7 +17,7 @@ MPRI_Reg_Rect = namedtuple("MPRI_Reg_Rect", ["x", "y", "h", "w"])
class PersonInfo:
"""Info about a person in the Photos library"""
def __init__(self, db=None, pk=None):
def __init__(self, db: "osxphotos.PhotosDB", pk: int):
"""Creates a new PersonInfo instance
Arguments:
@@ -25,8 +27,8 @@ class PersonInfo:
Returns:
PersonInfo instance
"""
self._db = db
self._pk = pk
self._db: "osxphotos.PhotosDB" = db
self._pk: int = pk
person = self._db._dbpersons_pk[pk]
self.uuid = person["uuid"]
@@ -72,6 +74,33 @@ class PersonInfo:
# no faces
return []
@property
def favorite(self):
"""Returns True if person is a favorite, False otherwise; Photos 5+ only; returns False on Photos <= 4"""
return self._db._dbpersons_pk[self._pk]["type"] == 1
@property
def sort_order(self):
"""Returns sort order of person; favorite persons are sorted before non-favorite persons"; Photos 5+ only; returns 0 on Photos <= 4"""
return self._db._dbpersons_pk[self._pk]["manualorder"]
@cached_property
def feature_less(self):
"""Returns True if person has been marked as "Feature This Person Less" in Photos, False otherwise; Photos 8+ only; returns False on Photos <= 7"""
if self._db.photos_version < 8:
return False
if results := self._db.execute(
"""
SELECT ZTYPE
FROM ZUSERFEEDBACK
WHERE ZPERSON = ?
""",
(self._pk,),
).fetchone():
return bool(results[0])
return False
def asdict(self):
"""Returns dictionary representation of class instance"""
keyphoto = self.keyphoto.uuid if self.keyphoto is not None else None
@@ -82,6 +111,9 @@ class PersonInfo:
"keyface": self.keyface,
"facecount": self.facecount,
"keyphoto": keyphoto,
"favorite": self.favorite,
"sort_order": self.sort_order,
"feature_less": self.feature_less,
}
def json(self):

181
osxphotos/photodates.py Normal file
View File

@@ -0,0 +1,181 @@
"""Utilities for working with Photo dates in Apple Photos; used by osxphotos timewarp command"""
from __future__ import annotations
import datetime
import pathlib
from typing import Callable
import photoscript
from strpdatetime import strpdatetime
from .datetime_utils import (
datetime_has_tz,
datetime_remove_tz,
datetime_tz_to_utc,
datetime_utc_to_local,
utc_offset_seconds,
)
from .phototz import PhotoTimeZone, PhotoTimeZoneUpdater
from .timeutils import update_datetime
from .timezones import Timezone
def update_photo_date_time(
photo: photoscript.Photo,
date,
time,
date_delta,
time_delta,
verbose: Callable,
):
"""Update date, time in photo"""
photo_date = photo.date
new_photo_date = update_datetime(
photo_date, date=date, time=time, date_delta=date_delta, time_delta=time_delta
)
filename = photo.filename
uuid = photo.uuid
if new_photo_date != photo_date:
photo.date = new_photo_date
verbose(
f"Updated date/time for photo [filename]{filename}[/filename] "
f"([uuid]{uuid}[/uuid]) from: [time]{photo_date}[/time] to [time]{new_photo_date}[/time]"
)
else:
verbose(
f"Skipped date/time update for photo [filename]{filename}[/filename] "
f"([uuid]{uuid}[/uuid]): nothing to do"
)
def update_photo_from_function(
library_path: str,
function: Callable,
verbose: Callable[..., None],
photo: photoscript.Photo,
path: str | None,
):
"""Update photo from function call"""
photo_tz_sec, _, photo_tz_name = PhotoTimeZone(
library_path=library_path
).get_timezone(photo)
dt_new, tz_new = function(
photo=photo,
path=path,
tz_sec=photo_tz_sec,
tz_name=photo_tz_name,
verbose=verbose,
)
if dt_new != photo.date:
old_date = photo.date
photo.date = dt_new
verbose(
f"Updated date/time for photo [filename]{photo.filename}[/filename] "
f"([uuid]{photo.uuid}[/uuid]) from: [time]{old_date}[/time] to [time]{dt_new}[/time]"
)
else:
verbose(
f"Skipped date/time update for photo [filename]{photo.filename}[/filename] "
f"([uuid]{photo.uuid}[/uuid]): nothing to do"
)
if tz_new != photo_tz_sec:
tz_updater = PhotoTimeZoneUpdater(
timezone=Timezone(tz_new), verbose=verbose, library_path=library_path
)
tz_updater.update_photo(photo)
else:
verbose(
f"Skipped timezone update for photo [filename]{photo.filename}[/filename] "
f"([uuid]{photo.uuid}[/uuid]): nothing to do"
)
def update_photo_time_for_new_timezone(
library_path: str,
photo: photoscript.Photo,
new_timezone: Timezone,
verbose: Callable[..., None],
):
"""Update time in photo to keep it the same time but in a new timezone
For example, photo time is 12:00+0100 and new timezone is +0200,
so adjust photo time by 1 hour so it will now be 12:00+0200 instead of
13:00+0200 as it would be with no adjustment to the time"""
old_timezone = PhotoTimeZone(library_path=library_path).get_timezone(photo)[0]
# need to move time in opposite direction of timezone offset so that
# photo time is the same time but in the new timezone
delta = old_timezone - new_timezone.offset
photo_date = photo.date
new_photo_date = update_datetime(
dt=photo_date, time_delta=datetime.timedelta(seconds=delta)
)
filename = photo.filename
uuid = photo.uuid
if photo_date != new_photo_date:
photo.date = new_photo_date
verbose(
f"Adjusted date/time for photo [filename]{filename}[/] ([uuid]{uuid}[/]) to [time]{new_photo_date}[/] "
f"to match previous time [time]{photo_date}[/] but in new timezone [tz]{new_timezone}[/]."
)
else:
verbose(
f"Skipping date/time update for photo [filename]{filename}[/] ([uuid]{photo.uuid}[/]), "
f"already matches new timezone [tz]{new_timezone}[/]"
)
def set_photo_date_from_filename(
photo: photoscript.Photo,
filepath: pathlib.Path | str,
parse_date: str,
verbose: Callable[..., None],
library_path: str | None = None,
) -> datetime.datetime | None:
"""Set date of photo from filename
Args:
photo: Photo to set date
filepath: Path to photo's original file
parse_date: strptime format string to parse date from filename
verbose: verbose function to use for logging
library_path: Path to Photos library; if not provided, will attempt to determine automatically
Returns:
datetime.datetime: date set on photo or None if date could not be parsed
"""
if not isinstance(filepath, pathlib.Path):
filepath = pathlib.Path(filepath)
try:
date = strpdatetime(filepath.name, parse_date)
except ValueError:
verbose(
f"[warning]Could not parse date from filename [filename]{filepath.name}[/][/]"
)
return None
# first, set date on photo without timezone (Photos will assume local timezone)
date_no_tz = datetime_remove_tz(date) if datetime_has_tz(date) else date
verbose(
f"Setting date of photo [filename]{filepath.name}[/] to [time]{date_no_tz.strftime('%Y-%m-%d %H:%M:%S')}[/]"
)
photo.date = date_no_tz
if datetime_has_tz(date):
# if timezone, need to update timezone and also the date/time to match
photo_tz_sec, _, photo_tz_name = PhotoTimeZone(
library_path=library_path
).get_timezone(photo)
tz_new_secs = int(utc_offset_seconds(date))
if photo_tz_sec != tz_new_secs:
tz_new = Timezone(tz_new_secs)
update_photo_time_for_new_timezone(library_path, photo, tz_new, verbose)
tz_updater = PhotoTimeZoneUpdater(
timezone=tz_new,
verbose=verbose,
library_path=library_path,
)
tz_updater.update_photo(photo)
return date

View File

@@ -1,6 +1,4 @@
"""
PhotoInfo class
Represents a single photo in the Photos library and provides access to the photo's attributes
""" PhotoInfo class: Represents a single photo in the Photos library and provides access to the photo's attributes
PhotosDB.photos() returns a list of PhotoInfo objects
"""
@@ -17,11 +15,13 @@ import pathlib
import plistlib
from datetime import timedelta, timezone
from functools import cached_property
from typing import Dict, Optional
from typing import Any, Dict, Optional
import yaml
from osxmetadata import OSXMetaData
import osxphotos
from ._constants import (
_DB_TABLE_NAMES,
_MOVIE_TYPE,
@@ -75,10 +75,10 @@ class PhotoInfo:
including keywords, persons, albums, uuid, path, etc.
"""
def __init__(self, db=None, uuid=None, info=None):
self._uuid = uuid
self._info = info
self._db = db
def __init__(self, db: "osxphotos.PhotosDB", uuid: str, info: dict[str, Any]):
self._uuid: str = uuid
self._info: dict[str, Any] = info
self._db: "osxphotos.PhotosDB" = db
self._verbose = self._db._verbose
@property

View File

@@ -3,18 +3,21 @@ PhotosDB class
Processes a Photos.app library database to extract information about photos
"""
from __future__ import annotations
import logging
import os
import os.path
import pathlib
import platform
import re
import sqlite3
import sys
import tempfile
from collections import OrderedDict
from collections.abc import Iterable
from datetime import datetime, timedelta, timezone
from typing import List, Optional
from typing import Any, List, Optional
from unicodedata import normalize
import bitmath
@@ -705,6 +708,8 @@ class PhotosDB:
"displayname": normalize_unicode(person[4]),
"photo_uuid": None,
"keyface_uuid": None,
"type": None, # Photos 5+
"manualorder": 0, # Photos 5+
}
try:
self._dbpersons_fullname[fullname].append(pk)
@@ -1687,7 +1692,9 @@ class PhotosDB:
ZPERSON.ZFULLNAME,
ZPERSON.ZFACECOUNT,
ZPERSON.ZKEYFACE,
ZPERSON.ZDISPLAYNAME
ZPERSON.ZDISPLAYNAME,
ZPERSON.ZTYPE,
ZPERSON.ZMANUALORDER
FROM ZPERSON
"""
)
@@ -1698,6 +1705,8 @@ class PhotosDB:
# 3 ZPERSON.ZFACECOUNT,
# 4 ZPERSON.ZKEYFACE,
# 5 ZPERSON.ZDISPLAYNAME
# 6 ZPERSON.ZTYPE, # ZTYPE = 1 == favorite, 0 == not favorite
# 7 ZPERSON.ZMANUALORDER # favorites are sorted by ZMANUALORDER
for person in c:
pk = person[0]
@@ -1715,6 +1724,8 @@ class PhotosDB:
"displayname": normalize_unicode(person[5]),
"photo_uuid": None,
"keyface_uuid": None,
"type": person[6],
"manualorder": person[7],
}
try:
self._dbpersons_fullname[fullname].append(pk)
@@ -3563,10 +3574,11 @@ class PhotosDB:
return photos
def execute(self, sql):
def execute(self, sql: str, params: Any | None = None) -> sqlite3.Cursor:
"""Execute sql statement and return cursor"""
self._db_connection, _ = self.get_db_connection()
return self._db_connection.cursor().execute(sql)
params = params or ()
return self._db_connection.cursor().execute(sql, params)
def _duplicate_signature(self, uuid):
"""Compute a signature for finding possible duplicates"""

View File

@@ -3,6 +3,7 @@
# Ensure you have a backup before using!
# You have been warned.
import datetime
import pathlib
import sqlite3
from typing import Callable, Optional, Tuple
@@ -147,6 +148,12 @@ class PhotoTimeZoneUpdater:
c = conn.cursor()
c.execute(sql_update)
conn.commit()
# now need to update some other property in the photo via Photos API or
# changes won't be synced to the cloud (#946)
photo.date = photo.date + datetime.timedelta(seconds=1)
photo.date = photo.date - datetime.timedelta(seconds=1)
self.verbose(
f"Updated timezone for photo [filename]{photo.filename}[/filename] ([uuid]{photo.uuid}[/uuid]) "
+ f"from [tz]{tz_name}[/tz], offset=[tz]{tz_offset}[/tz] "

View File

@@ -3,14 +3,14 @@
<plist version="1.0">
<dict>
<key>hostname</key>
<string>ddrucker-mba.local</string>
<string>Mac-mini.local</string>
<key>hostuuid</key>
<string>3C58BD83-C174-52E3-B12D-D7EBDED55622</string>
<string>8E774325-0506-5746-9991-6B8189271107</string>
<key>pid</key>
<integer>940</integer>
<integer>61681</integer>
<key>processname</key>
<string>photolibraryd</string>
<key>uid</key>
<integer>502</integer>
<integer>501</integer>
</dict>
</plist>

View File

@@ -17,6 +17,15 @@
<key>kZoomLevelIdentifierPhotosGrid</key>
<integer>1</integer>
</dict>
<key>PXPeopleCandidateWidgetKey</key>
<dict>
<key>PXPeopleCandidateWidgetKey2023.01.22</key>
<array>
<string>3DDC8F83-FDAB-4943-AE53-19428BEEED9D/L0/070</string>
</array>
</dict>
<key>PXPeopleHomeSortingType</key>
<integer>0</integer>
<key>Photos</key>
<dict>
<key>CollapsedSidebarSectionIdentifiers</key>

View File

@@ -902,13 +902,15 @@
<key>lastSeenDates</key>
<dict>
<key>com.apple.photos.CPAnalytics.assetCollectionViewed</key>
<string>11/12/22</string>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.mediaViewed</key>
<string>11/12/22</string>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.search.session</key>
<string>11/12/22</string>
<key>screen_CuratedLibrary_AllPhotos</key>
<string>11/12/22</string>
<string>1/22/23</string>
<key>screen_PhotosDetails_People</key>
<string>1/22/23</string>
<key>screen_PhotosView</key>
<string>11/12/22</string>
</dict>

View File

@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PLThumbnailManagerRebuildingTablesOnly</key>
<true/>
<key>PLThumbnailManagerThumbnailFormatKey</key>
<integer>5005</integer>
<key>PLThumbnailManagerThumbnailFormatsKey</key>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>LibrarySchemaVersion</key>
<integer>5001</integer>
<key>MetaSchemaVersion</key>
<integer>3</integer>
</dict>
</plist>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>hostname</key>
<string>Mac-mini.local</string>
<key>hostuuid</key>
<string>8E774325-0506-5746-9991-6B8189271107</string>
<key>pid</key>
<integer>61681</integer>
<key>processname</key>
<string>photolibraryd</string>
<key>uid</key>
<integer>501</integer>
</dict>
</plist>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>insertAlbum</key>
<array/>
<key>insertAsset</key>
<array/>
<key>insertHighlight</key>
<array/>
<key>insertMemory</key>
<array/>
<key>insertMoment</key>
<array/>
<key>removeAlbum</key>
<array/>
<key>removeAsset</key>
<array/>
<key>removeHighlight</key>
<array/>
<key>removeMemory</key>
<array/>
<key>removeMoment</key>
<array/>
<key>renamePerson</key>
<array/>
</dict>
</plist>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>embeddingVersion</key>
<string>1</string>
<key>featureFlags</key>
<string>319</string>
<key>featuredContentAllowed</key>
<string>1</string>
<key>localeIdentifier</key>
<string>en_US</string>
<key>sceneTaxonomySHA</key>
<string>64d078bafc0035e1ec26dfa565c2ac0479fcbab329fda1c16cd17e0fdbf2f4c0,4afa5d3c45c08a664cf73cff957aaeeae3a325d2970aada51268407b9ad0f03e</string>
<key>searchIndexVersion</key>
<string>16025</string>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CollapsedSidebarSectionIdentifiers</key>
<array/>
<key>IPXWorkspaceControllerZoomLevelsKey</key>
<dict>
<key>kZoomLevelIdentifierPhotosGrid</key>
<integer>2</integer>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>FaceProcessingInternalVersion</key>
<integer>11</integer>
</dict>
</plist>

View File

@@ -0,0 +1,910 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>firstSeenDates</key>
<dict>
<key>com.apple.photos.CPAnalytics.addAssetsToLibrary</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.appleMusicPreparationFailed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.appleMusicPreparationSucceeded</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.appleMusicPreparedToPlay</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.appleMusicSongDownloaded</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetCollectionBlocked</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetCollectionDeleted</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetCollectionFavorited</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetCollectionMoviePlayed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetCollectionUnfavorited</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetCollectionViewed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetExportItemPreparationCompleted</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetExportPreparationCanceled</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetExportPreparationCompleted</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetExportPreparationFailed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetFavorited</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetSharedStandardSelectionSize</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetUnfavorited</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetViewed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetsDeleted</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetsDeletedFromTrash</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.assetsRestored</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmAddAssetToLibrary</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmPublishFromDetailViewMenuAction</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmPublishFromForYouSendBackSuggestions</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmPublishFromForYouSuggestion</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmPublishFromMessagesSuggestion</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmPublishFromShareSheet</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmPublishFromUnknown</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmReceivedSharesOpened</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmReceivedSharesSeen</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmSentSharesOpened</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmSentSharesSeen</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmShareBackOpened</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmShareBackPresentable</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmShareBackShown</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmSuggestionComposeFlowOpened</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmSuggestionOpened</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.cmmSuggestionSeen</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationEventFailed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationEventOneUpSelect</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationEventSkip</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationFromAlbumSection</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationFromAlbumSelection</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationFromOneUpMergeAll</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationFromOneUpSelection</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationFromUnspecified</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationMerge1</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationMerge11+</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationMerge2</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationMerge3-5</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationMerge6-10</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationMergeAll</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.deduplicationSkipPerceptualMerge</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterAllItemsSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterDuplicatesSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterEditedSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterFavoritedSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterHeaderSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterIncludeSharedWithYouSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterKeywordHeaderSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterKeywordManagerSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterKeywordsSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterPhotosSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterSavedItemsOnlySelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterSharedLibraryAllDisplayed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterSharedLibraryAllSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterSharedLibraryDismissed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterSharedLibraryMineDisplayed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterSharedLibraryMineSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterSharedLibraryPresented</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterSharedLibrarySharedDisplayed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterSharedLibrarySharedSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterUnsavedItemsOnlySelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.filterVideosSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.firstTimeExperienceNotReady</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.firstTimeExperienceReady</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.flexMusicDownloadRequiredAtPlaybackTime</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.flexMusicSongArtworkDownloaded</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.flexMusicSongAudioDownloaded</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouInboxItemSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouInboxItemSelectedWithTypeCMMPublishedShare</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouInboxItemSelectedWithTypeCMMReceivedShare</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouInboxItemSelectedWithTypeSharedAlbumAccept</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouInboxItemSelectedWithTypeSharedAlbumCoalescedWithComments</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouInboxItemSelectedWithTypeSharedAlbumCoalescedWithCommentsAndLikes</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouInboxItemSelectedWithTypeSharedAlbumComment</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouInboxItemSelectedWithTypeSharedAlbumDecline</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouInboxItemSelectedWithTypeSharedAlbumInvitation</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouInboxItemSelectedWithTypeSharedAlbumLike</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouInboxItemSelectedWithTypeSharedAlbumPost</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouTabOpenedFromInAppUserNavigation</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouTabOpenedFromNotification</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouTabOpenedFromOtherURL</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouTabOpenedFromStateRestoration</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouTabOpenedFromUndefined</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.forYouTabOpenedFromWidget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeAlbumGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeAlbumListGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeCMMInviteGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeCMMSuggestionGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeCPLCMMSuggestionGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeContentSyndication</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeDebugGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeFooterGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeInboxGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeListViewGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeMemoryRowGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeNoContentGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeRecentPhotosGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeRecentSearchesGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeSearchZeroKeywordGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeSettingsAdvisory</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeSharedAlbumActivityGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeSharedAlbumGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeSharedAlbumInviteGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeSuggestedEditGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeSuggestionGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeSurveyCongratulations</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeSurveyQuestionGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetSeenWithTypeTapToRadarGadget</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetWithTypeMemoryRowGadgetSelectedAccessoryButtonWithTypeSeeAll</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.gadgetWithTypeSharedAlbumGadgetSelectedAccessoryButtonWithTypeSeeAll</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.infoPanelAddLocationTapped</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.infoPanelAdjustLocationTapped</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.infoPanelLocationTapped</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.mapViewAdjustLocationTapped</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.mediaViewed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.memoryCreatedViaAddToMemories</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.memoryNotificationResponded</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.memoryNotificationSeen</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigateToFailedToUploadItemsAlbumFailed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigateToFailedToUploadItemsAlbumSucceeded</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigatedToSharedAlbumActivityViewFromCollageView</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigatedToSharedAlbumActivityViewFromRecentActivityEntry</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigatedToSharedAlbumActivityViewFromSeeAllButton</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.favorites</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.hidden</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.imports</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.animated</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.bursts</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.cinematicVideos</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.depthEffect</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.livePhotos</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.longExposures</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.panoramas</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.proRes</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.raw</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.screenrecordings</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.screenshots</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.selfPortraits</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.slomoVideos</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.timelapses</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.mediaTypes.videos</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.people</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.places</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.recentlyedited</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.recentlysaved</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.navigationList.trashBin</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpCaptionEditExited</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpCaptionEditExitedWith1-10Characters</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpCaptionEditExitedWith101+Characters</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpCaptionEditExitedWith11+Hashtags</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpCaptionEditExitedWith11-20Characters</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpCaptionEditExitedWith1Hashtags</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpCaptionEditExitedWith21-30Characters</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpCaptionEditExitedWith2Hashtags</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpCaptionEditExitedWith31-50Characters</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpCaptionEditExitedWith3Hashtags</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpCaptionEditExitedWith4-5Hashtags</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpCaptionEditExitedWith51-100Characters</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpCaptionEditExitedWith6-10Hashtags</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.oneUpLivePhotoEffectApplied</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.addToPeopleHome</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.bootstrap.inlineControl.dismiss</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.bootstrap.inlineControl.review</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.bootstrap.mergeCandidates.confirmedAndRejectedCounts</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.bootstrap.speedbump.advance</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.bootstrap.speedbump.cancel</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.confirmAdditional.mergeCandidates.confirmedAndRejectedCounts</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.confirmAdditional.personSuggestions.confirmedAndRejectedCounts</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.detailView.keyPhotoChanged</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.detailView.notThisPerson</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.detailView.showFaces</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.manageTags.commitTapped</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.me.confirmed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.me.rejected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.naming.contactChosen</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.naming.personChosen</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.naming.skipped</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.naming.stringChosen</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.removeFromPeopleHome</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.untag.cancelTapped</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.untag.newTagTapped</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.people.untag.untagTapped</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosCloudQuotaOfferAdded</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosCloudQuotaOfferRemoved</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosCloudQuotaOfferReplaced</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsAllAssetsCounted</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth1</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth10</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth11-12</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth13-15</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth16-20</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth2</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth21-30</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth3</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth31-50</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth4</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth5</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth51+</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth6</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth7</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth8</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsNavigatedToDepth9</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsShowMoreButtonSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsSummaryAssetsCounted</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.photosDetailsSummaryButtonSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.places.locationAction</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.rendering.livePhotoEffectFailed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.rendering.livePhotoEffectPreviewRenderingDuration</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.search.session</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.search.siri</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.selectModeEntered</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.shareCanceled</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.shareCompleted</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.shareFailed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.sharedAlbumInvitationAccepted</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.sharedAlbumInvitationDeclined</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.sharedAlbumInvitationReportedAsJunk</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.sharedAlbumsActivityFeedPostLiked</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.sharedAlbumsActivityFeedPostUnliked</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.sharedLibrary.suggestionsBanner.dismissed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.sharedLibrary.suggestionsBanner.presented</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.sharedLibrary.suggestionsBanner.reviewed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportCancelledAfter10.0-60.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportCancelledAfter2.0-10.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportCancelledAfter&lt;2.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportCancelledAfter&gt;60.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportEndedSuccessfullyAfter0.0-1.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportEndedSuccessfullyAfter1.0-2.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportEndedSuccessfullyAfter10.0-20.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportEndedSuccessfullyAfter120.0-300.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportEndedSuccessfullyAfter2.0-5.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportEndedSuccessfullyAfter20.0-60.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportEndedSuccessfullyAfter300.0-600.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportEndedSuccessfullyAfter5.0-10.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportEndedSuccessfullyAfter60.0-120.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportEndedSuccessfullyAfter600.0-3600.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportEndedSuccessfullyAfter&lt;0.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportEndedSuccessfullyAfter&gt;3600.0Seconds</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportFailed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowExportStarted</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction0.0-0.1</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction0.1-0.2</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction0.2-0.2</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction0.3-0.4</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction0.4-0.5</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction0.5-0.6</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction0.6-0.7</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction0.7-0.8</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction0.8-0.9</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction0.9-1.0</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction1.0-1.5</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction1.5-2.0</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction2.0-3.0</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction3.0-5.0</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction&lt;0.0</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedAfterTimeFraction&gt;5.0</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedByEndReached</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedByUndefined</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackEndedByUser</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStarted</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStartedWith0-Assets</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStartedWith1-5Assets</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStartedWith1001+Assets</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStartedWith101-200Assets</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStartedWith11-15Assets</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStartedWith16-20Assets</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStartedWith201-300Assets</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStartedWith21-30Assets</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStartedWith301-500Assets</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStartedWith31-50Assets</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStartedWith501-1000Assets</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStartedWith51-100Assets</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.slideshowPlaybackStartedWith6-10Assets</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.syndicatedAssetsFilterTipAnchorButtonTapped</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.syndicatedAssetsFilterTipDismissed</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.syndicatedAssetsFilterTipPresented</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.syndicatedAssetsSaved</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.syndicationSuggestionRemoved</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.tabIdentifierChanged</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.toggleMineAndSharedSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.toggleMyPhotosOnlySelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.userChoices.livePhotoEffectBounceSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.userChoices.livePhotoEffectLongExposureSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.userChoices.livePhotoEffectLoopSelected</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.userChoices.livePhotoEffectsAppeared</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.viewScrolledToBottom</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.viewScrolledToInitialPosition</key>
<string>1/22/23</string>
<key>com.apple.photos.CPAnalytics.widget.open</key>
<string>1/22/23</string>
<key>com.apple.photos.cpa.active_user_feature.actionOnSharedLibrarySuggestions</key>
<string>1/22/23</string>
<key>com.apple.photos.cpa.active_user_feature.interactiveMemoryExport</key>
<string>1/22/23</string>
<key>com.apple.photos.cpa.active_user_feature.interactiveMemoryPlayback</key>
<string>1/22/23</string>
<key>com.apple.photos.cpa.active_user_feature.memoryMoviePlayed</key>
<string>1/22/23</string>
<key>com.apple.photos.cpa.active_user_feature.memoryViewed</key>
<string>1/22/23</string>
<key>com.apple.photos.cpa.active_user_feature.mobileSlideShowActive</key>
<string>1/22/23</string>
<key>com.apple.photos.cpa.active_user_feature.slideshowExported</key>
<string>1/22/23</string>
<key>com.apple.photos.cpa.active_user_feature.slideshowPlayed</key>
<string>1/22/23</string>
<key>com.apple.photos.edit.perf.exitedit</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.appleMusicFixation</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurred</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInAdditionalAutoEditDecisionLists</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInAssets</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInAssetsPreloading</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInAutoEditClip</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInAutoEditDecisionLists</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInAutoEditTransitionInfo</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInColorNormalization</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInCuratedSongs</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInInitialStyle</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInMovieHighlights</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInMusicPlayback</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInPersistableRecipe</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInPersistence</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInRecipePersistence</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInStoryModel</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInStyleManager</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInStyles</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInTargetDurationCuration</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInTimelineManager</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInTimelineValidation</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryErrorOccurredInTransitions</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryExportCancelled</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryExportFailed</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryExported</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStarted</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedByAutoplayedRelated</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedByUserSelectingRelated</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedWith1-10CuratedAssets</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedWith10001-20000CuratedAssets</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedWith1001-2000CuratedAssets</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedWith101-200CuratedAssets</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedWith11-50CuratedAssets</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedWith20000+CuratedAssets</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedWith2001-5000CuratedAssets</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedWith201-300CuratedAssets</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedWith301-500CuratedAssets</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedWith5001-10000CuratedAssets</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedWith501-1000CuratedAssets</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryFullscreenPlaybackStartedWith51-100CuratedAssets</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryMusicFellBackToLocalFlexSong</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryMusicUsedFlexMusic</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryMusicUseedAppleMusic</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackFinishedMuted</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackFinishedTruncated</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackFinishedUnmuted</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackFinishedWith0Pauses</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackFinishedWith1-2Pauses</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackFinishedWith101+Pauses</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackFinishedWith11-50Pauses</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackFinishedWith3-5Pauses</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackFinishedWith51-100Pauses</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackFinishedWith6-10Pauses</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackMutedDueToExplicitUserAction</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackMutedDueToSilentModeSwitch</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackUnmutedDueToExplicitUserAction</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackUnmutedDueToSilentModeSwitch</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackUnmutedDueToSongPick</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryPlaybackUnmutedDueToVolumeIncrease</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryRecipeErrorOccurred</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemorySessionBegan</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemorySessionEnded</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemorySessionPaused</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemorySessionPlayed</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryTimelinePlayedWith0-49PercentTransitionsOnBar</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryTimelinePlayedWith50-74PercentTransitionsOnBar</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryTimelinePlayedWith75-84PercentTransitionsOnBar</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryTimelinePlayedWith85-94PercentTransitionsOnBar</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.interactiveMemoryTimelinePlayedWith95-100PercentTransitionsOnBar</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.playbackLaunchPerformance</key>
<string>1/22/23</string>
<key>com.apple.photos.memory.playbackReliability</key>
<string>1/22/23</string>
<key>screen_CuratedLibrary_AllPhotos</key>
<string>1/22/23</string>
<key>screen_CuratedLibrary_Days</key>
<string>1/22/23</string>
<key>screen_CuratedLibrary_Months</key>
<string>1/22/23</string>
<key>screen_CuratedLibrary_Years</key>
<string>1/22/23</string>
<key>screen_DuplicatesAlbum</key>
<string>1/22/23</string>
<key>screen_FavoriteMemories</key>
<string>1/22/23</string>
<key>screen_IPXFeedViewController</key>
<string>1/22/23</string>
<key>screen_InteractiveMemory</key>
<string>1/22/23</string>
<key>screen_InteractiveMemoryBrowserGrid</key>
<string>1/22/23</string>
<key>screen_InteractiveMemoryStyleSwitcher</key>
<string>1/22/23</string>
<key>screen_MFMailComposeViewController</key>
<string>1/22/23</string>
<key>screen_MFMessageComposeViewController</key>
<string>1/22/23</string>
<key>screen_Memories</key>
<string>1/22/23</string>
<key>screen_MemoriesFeed</key>
<string>1/22/23</string>
<key>screen_MemoriesWidget</key>
<string>1/22/23</string>
<key>screen_ObjectManipulationViewController</key>
<string>1/22/23</string>
<key>screen_PMEditorNavigationController</key>
<string>1/22/23</string>
<key>screen_PMiOSMainViewController</key>
<string>1/22/23</string>
<key>screen_PXAssistantController</key>
<string>1/22/23</string>
<key>screen_PXCMMAssetsViewController</key>
<string>1/22/23</string>
<key>screen_PXEducationalTipViewController</key>
<string>1/22/23</string>
<key>screen_PXFeedViewController</key>
<string>1/22/23</string>
<key>screen_PXFeedbackTapToRadarViewController</key>
<string>1/22/23</string>
<key>screen_PXFloatingCardViewController</key>
<string>1/22/23</string>
<key>screen_PXForYouGadgetViewController</key>
<string>1/22/23</string>
<key>screen_PXPeopleBootstrapConfirmationViewController</key>
<string>1/22/23</string>
<key>screen_PXPeopleBootstrapSummaryViewController</key>
<string>1/22/23</string>
<key>screen_PXPeopleCollectionViewController</key>
<string>1/22/23</string>
<key>screen_PXPeopleConfirmationSummaryViewController</key>
<string>1/22/23</string>
<key>screen_PXPeopleDetailViewController</key>
<string>1/22/23</string>
<key>screen_PXPeopleNamePickerViewController</key>
<string>1/22/23</string>
<key>screen_PXPeopleRecoCollectionViewController</key>
<string>1/22/23</string>
<key>screen_PXPlacesMapInfoViewController</key>
<string>1/22/23</string>
<key>screen_PXPlacesMapViewController</key>
<string>1/22/23</string>
<key>screen_PXSharedLibraryAssistantCameraViewController</key>
<string>1/22/23</string>
<key>screen_PXSharedLibraryAssistantHowToViewController</key>
<string>1/22/23</string>
<key>screen_PXSharedLibraryAssistantReviewParticipantsViewController</key>
<string>1/22/23</string>
<key>screen_PXSharedLibraryAssistantRulesViewController</key>
<string>1/22/23</string>
<key>screen_PXSharedLibraryAssistantSummaryViewController</key>
<string>1/22/23</string>
<key>screen_PXSurveyRadarReporterViewController</key>
<string>1/22/23</string>
<key>screen_PXUIPeopleBootstrapNamingViewController</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_Collection</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_CuratedLibraryDays</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_CuratedLibraryMonths</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_CuratedLibraryYears</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_Memories</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_Moment</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_NonTracking</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_OneUpAccessory</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_OtherAlbums</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_People</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_Places</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_RelatedWidget</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_Search</key>
<string>1/22/23</string>
<key>screen_PhotosDetails_Year</key>
<string>1/22/23</string>
<key>screen_PhotosUIApps.PUXStoryColorGradeEditorViewController</key>
<string>1/22/23</string>
<key>screen_PhotosUIApps.PUXStoryExportActivityPreviewViewController</key>
<string>1/22/23</string>
<key>screen_PhotosUIApps.PUXStoryExportActivityViewController</key>
<string>1/22/23</string>
<key>screen_PhotosUIApps.PUXStoryMusicEditorViewController</key>
<string>1/22/23</string>
<key>screen_PhotosView</key>
<string>1/22/23</string>
<key>screen_SBSUIWallpaperPreviewViewController</key>
<string>1/22/23</string>
<key>screen_SLComposeViewController</key>
<string>1/22/23</string>
<key>screen_TPKContentPopoverViewController</key>
<string>1/22/23</string>
<key>screen_UIImagePickerController</key>
<string>1/22/23</string>
<key>screen__UIActivityUserDefaultsViewController</key>
<string>1/22/23</string>
</dict>
<key>lastSeenDates</key>
<dict>
<key>screen_CuratedLibrary_AllPhotos</key>
<string>1/22/23</string>
<key>screen_PhotosView</key>
<string>1/22/23</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BackgroundHighlightCollection</key>
<date>2021-10-09T17:36:25Z</date>
<key>BackgroundHighlightEnrichment</key>
<date>2021-10-09T17:36:25Z</date>
<key>BackgroundJobAssetRevGeocode</key>
<date>2021-10-09T17:36:25Z</date>
<key>BackgroundJobSearch</key>
<date>2021-10-09T17:36:25Z</date>
<key>BackgroundPeopleSuggestion</key>
<date>2021-10-09T17:36:24Z</date>
<key>BackgroundUserBehaviorProcessor</key>
<date>2021-10-07T03:30:30Z</date>
<key>PhotoAnalysisGraphLastBackgroundGraphConsistencyUpdateJobDateKey</key>
<date>2021-10-07T03:30:29Z</date>
<key>PhotoAnalysisGraphLastBackgroundGraphRebuildJobDate</key>
<date>2021-10-07T03:30:29Z</date>
<key>PhotoAnalysisGraphLastBackgroundMemoryGenerationJobDate</key>
<date>2021-10-09T17:36:25Z</date>
<key>SiriPortraitDonation</key>
<date>2021-10-08T20:51:05Z</date>
</dict>
</plist>

Some files were not shown because too many files have changed in this diff Show More