Added support for projects, implements #559

This commit is contained in:
Rhet Turnbull 2021-12-31 07:30:20 -08:00
parent 690d981f31
commit 44594a8e43
231 changed files with 1239 additions and 5545 deletions

View File

@ -14,7 +14,7 @@ OSXPhotos provides the ability to interact with and query Apple's Photos.app lib
# Table of Contents # Table of Contents
* [Supported operating systems](#supported-operating-systems) * [Supported operating systems](#supported-operating-systems)
* [Installation instructions](#installation-instructions) * [Installation](#installation)
* [Command Line Usage](#command-line-usage) * [Command Line Usage](#command-line-usage)
+ [Command line examples](#command-line-examples) + [Command line examples](#command-line-examples)
+ [Tutorial](#tutorial) + [Tutorial](#tutorial)
@ -25,6 +25,7 @@ OSXPhotos provides the ability to interact with and query Apple's Photos.app lib
+ [ExifInfo](#exifinfo) + [ExifInfo](#exifinfo)
+ [AlbumInfo](#albuminfo) + [AlbumInfo](#albuminfo)
+ [ImportInfo](#importinfo) + [ImportInfo](#importinfo)
+ [ProjectInfo](#projectinfo)
+ [FolderInfo](#folderinfo) + [FolderInfo](#folderinfo)
+ [PlaceInfo](#placeinfo) + [PlaceInfo](#placeinfo)
+ [ScoreInfo](#scoreinfo) + [ScoreInfo](#scoreinfo)
@ -1714,7 +1715,7 @@ Substitution Description
{lf} A line feed: '\n', alias for {newline} {lf} A line feed: '\n', alias for {newline}
{cr} A carriage return: '\r' {cr} A carriage return: '\r'
{crlf} a carriage return + line feed: '\r\n' {crlf} a carriage return + line feed: '\r\n'
{osxphotos_version} The osxphotos version, e.g. '0.43.9' {osxphotos_version} The osxphotos version, e.g. '0.44.0'
{osxphotos_cmd_line} The full command line used to run osxphotos {osxphotos_cmd_line} The full command line used to run osxphotos
The following substitutions may result in multiple values. Thus if specified for The following substitutions may result in multiple values. Thus if specified for
@ -1729,6 +1730,13 @@ Substitution Description
{folder_album} Folder path + album photo is contained in. e.g. {folder_album} Folder path + album photo is contained in. e.g.
'Folder/Subfolder/Album' or just 'Album' if no 'Folder/Subfolder/Album' or just 'Album' if no
enclosing folder enclosing folder
{project} Project(s) photo is contained in (such as greeting
cards, calendars, slideshows)
{album_project} Album(s) and project(s) photo is contained in; treats
projects as regular albums
{folder_album_project} Folder path + album (includes projects as albums)
photo is contained in. e.g. 'Folder/Subfolder/Album'
or just 'Album' if no enclosing folder
{keyword} Keyword(s) assigned to photo {keyword} Keyword(s) assigned to photo
{person} Person(s) / face(s) in a photo {person} Person(s) / face(s) in a photo
{label} Image categorization label associated with a photo {label} Image categorization label associated with a photo
@ -2103,7 +2111,7 @@ keywords = photosdb.keywords
Returns a list of the keywords found in the Photos library Returns a list of the keywords found in the Photos library
#### `album_info` #### <a name="photosdbalbuminfo">`album_info`</a>
```python ```python
# assumes photosdb is a PhotosDB object (see above) # assumes photosdb is a PhotosDB object (see above)
albums = photosdb.album_info albums = photosdb.album_info
@ -2133,6 +2141,10 @@ Returns list of shared album names found in photos database (e.g. albums shared
Returns a list of [ImportInfo](#importinfo) objects representing the import sessions for the database. Returns a list of [ImportInfo](#importinfo) objects representing the import sessions for the database.
#### `project_info`
Returns a list of [ProjectInfo](#projectinfo) objects representing the projects/creations (cards, calendars, etc.) in the database.
#### `folder_info` #### `folder_info`
```python ```python
# assumes photosdb is a PhotosDB object (see above) # assumes photosdb is a PhotosDB object (see above)
@ -2422,11 +2434,15 @@ Returns a list of keywords (e.g. tags) applied to the photo
Returns a list of albums the photo is contained in. See also [album_info](#album_info). Returns a list of albums the photo is contained in. See also [album_info](#album_info).
#### `album_info` #### `album_info`
Returns a list of [AlbumInfo](#AlbumInfo) objects representing the albums the photo is contained in. See also [albums](#albums). Returns a list of [AlbumInfo](#AlbumInfo) objects representing the albums the photo is contained in or empty list of the photo is not in any albums. See also [albums](#albums).
#### `import_info` #### `import_info`
Returns an [ImportInfo](#importinfo) object representing the import session associated with the photo or `None` if there is no associated import session. Returns an [ImportInfo](#importinfo) object representing the import session associated with the photo or `None` if there is no associated import session.
#### `project_info`
Returns a list of [ProjectInfo](#projectinfo) objects representing projects/creations (cards, calendars, etc.) the photo is contained in or empty list if there are no projects associated with the photo.
#### `persons` #### `persons`
Returns a list of the names of the persons in the photo Returns a list of the names of the persons in the photo
@ -2934,6 +2950,23 @@ Returns the start date as a timezone aware datetime.datetime object for when the
#### `end_date` #### `end_date`
Returns the end date as a timezone aware datetime.datetime object for when the import session completed. Returns the end date as a timezone aware datetime.datetime object for when the import session completed.
### ProjectInfo
PhotosDB.projcet_info returns a list of ProjectInfo objects. Each ProjectInfo object represents a project in the library. PhotoInfo.project_info returns a list of ProjectInfo objects for each project the photo is contained in.
Projects (found under "My Projects" in Photos) are projects or creations such as cards, calendars, and slideshows created in Photos. osxphotos provides only very basic information about projects and projects created with third party plugins may not accessible to osxphotos.
#### `uuid`
Returns the universally unique identifier (uuid) of the project. This is how Photos keeps track of individual objects within the database.
#### `title`
Returns the title or name of the project.
#### <a name="projectphotos">`photos`</a>
Returns a list of [PhotoInfo](#PhotoInfo) objects representing each photo contained in the project.
#### `creation_date`
Returns the creation date as a timezone aware datetime.datetime object of the project.
### FolderInfo ### FolderInfo
PhotosDB.folder_info returns a list of FolderInfo objects representing the top level folders in the library. Each FolderInfo object represents a single folder in the Photos library. PhotosDB.folder_info returns a list of FolderInfo objects representing the top level folders in the library. Each FolderInfo object represents a single folder in the Photos library.
@ -3584,10 +3617,13 @@ The following template field substitutions are availabe for use the templating s
|{lf}|A line feed: '\n', alias for {newline}| |{lf}|A line feed: '\n', alias for {newline}|
|{cr}|A carriage return: '\r'| |{cr}|A carriage return: '\r'|
|{crlf}|a carriage return + line feed: '\r\n'| |{crlf}|a carriage return + line feed: '\r\n'|
|{osxphotos_version}|The osxphotos version, e.g. '0.43.9'| |{osxphotos_version}|The osxphotos version, e.g. '0.44.0'|
|{osxphotos_cmd_line}|The full command line used to run osxphotos| |{osxphotos_cmd_line}|The full command line used to run osxphotos|
|{album}|Album(s) photo is contained in| |{album}|Album(s) photo is contained in|
|{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder| |{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder|
|{project}|Project(s) photo is contained in (such as greeting cards, calendars, slideshows)|
|{album_project}|Album(s) and project(s) photo is contained in; treats projects as regular albums|
|{folder_album_project}|Folder path + album (includes projects as albums) photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder|
|{keyword}|Keyword(s) assigned to photo| |{keyword}|Keyword(s) assigned to photo|
|{person}|Person(s) / face(s) in a photo| |{person}|Person(s) / face(s) in a photo|
|{label}|Image categorization label associated with a photo (Photos 5+ only). Labels are added automatically by Photos using machine learning algorithms to categorize images. These are not the same as {keyword} which refers to the user-defined keywords/tags applied in Photos.| |{label}|Image categorization label associated with a photo (Photos 5+ only). Labels are added automatically by Photos using machine learning algorithms to categorize images. These are not the same as {keyword} which refers to the user-defined keywords/tags applied in Photos.|

View File

@ -1,4 +1,4 @@
# Sphinx build info version 1 # Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 6a7b21011951131043e717993112beb1 config: 4b8efce5e11b970d619d6d5988967d84
tags: 645f666f9bcd5a90fca523b33c5a78b7 tags: 645f666f9bcd5a90fca523b33c5a78b7

View File

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

View File

@ -1,7 +1,7 @@
pre { line-height: 125%; } pre { line-height: 125%; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc } .highlight .hll { background-color: #ffffcc }
.highlight { background: #f8f8f8; } .highlight { background: #f8f8f8; }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,8 +4,9 @@
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Welcome to osxphotoss documentation! &#8212; osxphotos 0.43.9 documentation</title>
<title>Welcome to osxphotoss documentation! &#8212; osxphotos 0.44.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" /> <link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script> <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
@ -31,30 +32,30 @@
<div class="body" role="main"> <div class="body" role="main">
<div class="section" id="welcome-to-osxphotos-s-documentation"> <section id="welcome-to-osxphotos-s-documentation">
<h1>Welcome to osxphotoss documentation!<a class="headerlink" href="#welcome-to-osxphotos-s-documentation" title="Permalink to this headline"></a></h1> <h1>Welcome to osxphotoss documentation!<a class="headerlink" href="#welcome-to-osxphotos-s-documentation" title="Permalink to this headline"></a></h1>
</div> </section>
<div class="section" id="osxphotos"> <section id="osxphotos">
<h1>OSXPhotos<a class="headerlink" href="#osxphotos" title="Permalink to this headline"></a></h1> <h1>OSXPhotos<a class="headerlink" href="#osxphotos" title="Permalink to this headline"></a></h1>
<div class="section" id="what-is-osxphotos"> <section id="what-is-osxphotos">
<h2>What is osxphotos?<a class="headerlink" href="#what-is-osxphotos" title="Permalink to this headline"></a></h2> <h2>What is osxphotos?<a class="headerlink" href="#what-is-osxphotos" title="Permalink to this headline"></a></h2>
<p>OSXPhotos provides both the ability to interact with and query Apples Photos.app library on macOS directly from your python code <p>OSXPhotos provides both the ability to interact with and query Apples Photos.app library on macOS directly from your python code
as well as a very flexible command line interface (CLI) app for exporting photos. as well as a very flexible command line interface (CLI) app for exporting photos.
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 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.</p> You can also easily export both the original and edited photos.</p>
</div> </section>
<div class="section" id="supported-operating-systems"> <section id="supported-operating-systems">
<h2>Supported operating systems<a class="headerlink" href="#supported-operating-systems" title="Permalink to this headline"></a></h2> <h2>Supported operating systems<a class="headerlink" href="#supported-operating-systems" title="Permalink to this headline"></a></h2>
<p>Only works on macOS (aka Mac OS X). Tested on macOS Sierra (10.12.6) through macOS Big Sur (11.3).</p> <p>Only works on macOS (aka Mac OS X). Tested on macOS Sierra (10.12.6) through macOS Big Sur (11.3).</p>
<p>If you have access to macOS 12 / Monterey beta and would like to help ensure osxphotos is compatible, please contact me via GitHub.</p> <p>If you have access to macOS 12 / Monterey beta and would like to help ensure osxphotos is compatible, please contact me via GitHub.</p>
<p>This package will read Photos databases for any supported version on any supported macOS version. <p>This package will read Photos databases for any supported version on any supported macOS version.
E.g. you can read a database created with Photos 5.0 on MacOS 10.15 on a machine running macOS 10.12 and vice versa.</p> E.g. you can read a database created with Photos 5.0 on MacOS 10.15 on a machine running macOS 10.12 and vice versa.</p>
<p>Requires python &gt;= <code class="docutils literal notranslate"><span class="pre">3.7</span></code>.</p> <p>Requires python &gt;= <code class="docutils literal notranslate"><span class="pre">3.7</span></code>.</p>
</div> </section>
<div class="section" id="installation"> <section id="installation">
<h2>Installation<a class="headerlink" href="#installation" title="Permalink to this headline"></a></h2> <h2>Installation<a class="headerlink" href="#installation" title="Permalink to this headline"></a></h2>
<p>If you are new to python and just want to use the command line application, I recommend you to install using pipx. See other advanced options below.</p> <p>If you are new to python and just want to use the command line application, I recommend you to install using pipx. See other advanced options below.</p>
<div class="section" id="installation-using-pipx"> <section id="installation-using-pipx">
<h3>Installation using pipx<a class="headerlink" href="#installation-using-pipx" title="Permalink to this headline"></a></h3> <h3>Installation using pipx<a class="headerlink" href="#installation-using-pipx" title="Permalink to this headline"></a></h3>
<p>If you arent familiar with installing python applications, I recommend you install <code class="docutils literal notranslate"><span class="pre">osxphotos</span></code> with <a class="reference external" href="https://github.com/pipxproject/pipx">pipx</a>. If you use <code class="docutils literal notranslate"><span class="pre">pipx</span></code>, you will not need to create a virtual environment as <code class="docutils literal notranslate"><span class="pre">pipx</span></code> takes care of this. The easiest way to do this on a Mac is to use <a class="reference external" href="https://brew.sh/">homebrew</a>:</p> <p>If you arent familiar with installing python applications, I recommend you install <code class="docutils literal notranslate"><span class="pre">osxphotos</span></code> with <a class="reference external" href="https://github.com/pipxproject/pipx">pipx</a>. If you use <code class="docutils literal notranslate"><span class="pre">pipx</span></code>, you will not need to create a virtual environment as <code class="docutils literal notranslate"><span class="pre">pipx</span></code> takes care of this. The easiest way to do this on a Mac is to use <a class="reference external" href="https://brew.sh/">homebrew</a>:</p>
<ul class="simple"> <ul class="simple">
@ -64,15 +65,15 @@ E.g. you can read a database created with Photos 5.0 on MacOS 10.15 on a machine
<li><p>Then type this: <code class="docutils literal notranslate"><span class="pre">pipx</span> <span class="pre">install</span> <span class="pre">osxphotos</span></code></p></li> <li><p>Then type this: <code class="docutils literal notranslate"><span class="pre">pipx</span> <span class="pre">install</span> <span class="pre">osxphotos</span></code></p></li>
<li><p>Now you should be able to run <code class="docutils literal notranslate"><span class="pre">osxphotos</span></code> by typing: <code class="docutils literal notranslate"><span class="pre">osxphotos</span></code></p></li> <li><p>Now you should be able to run <code class="docutils literal notranslate"><span class="pre">osxphotos</span></code> by typing: <code class="docutils literal notranslate"><span class="pre">osxphotos</span></code></p></li>
</ul> </ul>
</div> </section>
<div class="section" id="installation-using-pip"> <section id="installation-using-pip">
<h3>Installation using pip<a class="headerlink" href="#installation-using-pip" title="Permalink to this headline"></a></h3> <h3>Installation using pip<a class="headerlink" href="#installation-using-pip" title="Permalink to this headline"></a></h3>
<p>You can also install directly from <a class="reference external" href="https://pypi.org/project/osxphotos/">pypi</a>:</p> <p>You can also install directly from <a class="reference external" href="https://pypi.org/project/osxphotos/">pypi</a>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pip</span> <span class="n">install</span> <span class="n">osxphotos</span> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pip</span> <span class="n">install</span> <span class="n">osxphotos</span>
</pre></div> </pre></div>
</div> </div>
</div> </section>
<div class="section" id="installation-from-git-repository"> <section id="installation-from-git-repository">
<h3>Installation from git repository<a class="headerlink" href="#installation-from-git-repository" title="Permalink to this headline"></a></h3> <h3>Installation from git repository<a class="headerlink" href="#installation-from-git-repository" title="Permalink to this headline"></a></h3>
<p>OSXPhotos uses setuptools, thus simply run:</p> <p>OSXPhotos uses setuptools, thus simply run:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">git</span> <span class="n">clone</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">RhetTbull</span><span class="o">/</span><span class="n">osxphotos</span><span class="o">.</span><span class="n">git</span> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">git</span> <span class="n">clone</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">RhetTbull</span><span class="o">/</span><span class="n">osxphotos</span><span class="o">.</span><span class="n">git</span>
@ -87,9 +88,9 @@ I recommend you install the latest version from <a class="reference external" hr
libraries. If you just want to use the command line utility, you can download a pre-built executable of the latest libraries. If you just want to use the command line utility, you can download a pre-built executable of the latest
<a class="reference external" href="https://github.com/RhetTbull/osxphotos/releases">release</a> or you can install via <code class="docutils literal notranslate"><span class="pre">pip</span></code> which also installs the command line app. <a class="reference external" href="https://github.com/RhetTbull/osxphotos/releases">release</a> or you can install via <code class="docutils literal notranslate"><span class="pre">pip</span></code> which also installs the command line app.
If you arent comfortable with running python on your Mac, start with the pre-built executable or <code class="docutils literal notranslate"><span class="pre">pipx</span></code> as described above.</p> If you arent comfortable with running python on your Mac, start with the pre-built executable or <code class="docutils literal notranslate"><span class="pre">pipx</span></code> as described above.</p>
</div> </section>
</div> </section>
<div class="section" id="command-line-usage"> <section id="command-line-usage">
<h2>Command Line Usage<a class="headerlink" href="#command-line-usage" title="Permalink to this headline"></a></h2> <h2>Command Line Usage<a class="headerlink" href="#command-line-usage" title="Permalink to this headline"></a></h2>
<p>This package will install a command line utility called <code class="docutils literal notranslate"><span class="pre">osxphotos</span></code> that allows you to query the Photos database and export photos. <p>This package will install a command line utility called <code class="docutils literal notranslate"><span class="pre">osxphotos</span></code> that allows you to query the Photos database and export photos.
Alternatively, you can also run the command line utility like this: <code class="docutils literal notranslate"><span class="pre">python3</span> <span class="pre">-m</span> <span class="pre">osxphotos</span></code></p> Alternatively, you can also run the command line utility like this: <code class="docutils literal notranslate"><span class="pre">python3</span> <span class="pre">-m</span> <span class="pre">osxphotos</span></code></p>
@ -127,38 +128,38 @@ Alternatively, you can also run the command line utility like this: <code class=
</pre></div> </pre></div>
</div> </div>
<p>To get help on a specific command, use <code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">help</span> <span class="pre">&lt;command_name&gt;</span></code></p> <p>To get help on a specific command, use <code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">help</span> <span class="pre">&lt;command_name&gt;</span></code></p>
<div class="section" id="command-line-examples"> <section id="command-line-examples">
<h3>Command line examples<a class="headerlink" href="#command-line-examples" title="Permalink to this headline"></a></h3> <h3>Command line examples<a class="headerlink" href="#command-line-examples" title="Permalink to this headline"></a></h3>
<div class="section" id="export-all-photos-to-desktop-export-group-in-folders-by-date-created"> <section id="export-all-photos-to-desktop-export-group-in-folders-by-date-created">
<h4>export all photos to ~/Desktop/export group in folders by date created<a class="headerlink" href="#export-all-photos-to-desktop-export-group-in-folders-by-date-created" title="Permalink to this headline"></a></h4> <h4>export all photos to ~/Desktop/export group in folders by date created<a class="headerlink" href="#export-all-photos-to-desktop-export-group-in-folders-by-date-created" title="Permalink to this headline"></a></h4>
<p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">export</span> <span class="pre">--export-by-date</span> <span class="pre">~/Pictures/Photos\</span> <span class="pre">Library.photoslibrary</span> <span class="pre">~/Desktop/export</span></code></p> <p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">export</span> <span class="pre">--export-by-date</span> <span class="pre">~/Pictures/Photos\</span> <span class="pre">Library.photoslibrary</span> <span class="pre">~/Desktop/export</span></code></p>
<p><strong>Note</strong>: Photos library/database path can also be specified using <code class="docutils literal notranslate"><span class="pre">--db</span></code> option:</p> <p><strong>Note</strong>: Photos library/database path can also be specified using <code class="docutils literal notranslate"><span class="pre">--db</span></code> option:</p>
<p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">export</span> <span class="pre">--export-by-date</span> <span class="pre">--db</span> <span class="pre">~/Pictures/Photos\</span> <span class="pre">Library.photoslibrary</span> <span class="pre">~/Desktop/export</span></code></p> <p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">export</span> <span class="pre">--export-by-date</span> <span class="pre">--db</span> <span class="pre">~/Pictures/Photos\</span> <span class="pre">Library.photoslibrary</span> <span class="pre">~/Desktop/export</span></code></p>
</div> </section>
<div class="section" id="find-all-photos-with-keyword-kids-and-output-results-to-json-file-named-results-json"> <section id="find-all-photos-with-keyword-kids-and-output-results-to-json-file-named-results-json">
<h4>find all photos with keyword “Kids” and output results to json file named results.json:<a class="headerlink" href="#find-all-photos-with-keyword-kids-and-output-results-to-json-file-named-results-json" title="Permalink to this headline"></a></h4> <h4>find all photos with keyword “Kids” and output results to json file named results.json:<a class="headerlink" href="#find-all-photos-with-keyword-kids-and-output-results-to-json-file-named-results-json" title="Permalink to this headline"></a></h4>
<p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">query</span> <span class="pre">--keyword</span> <span class="pre">Kids</span> <span class="pre">--json</span> <span class="pre">~/Pictures/Photos\</span> <span class="pre">Library.photoslibrary</span> <span class="pre">&gt;results.json</span></code></p> <p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">query</span> <span class="pre">--keyword</span> <span class="pre">Kids</span> <span class="pre">--json</span> <span class="pre">~/Pictures/Photos\</span> <span class="pre">Library.photoslibrary</span> <span class="pre">&gt;results.json</span></code></p>
</div> </section>
<div class="section" id="export-photos-to-file-structure-based-on-4-digit-year-and-full-name-of-month-of-photo-s-creation-date"> <section id="export-photos-to-file-structure-based-on-4-digit-year-and-full-name-of-month-of-photo-s-creation-date">
<h4>export photos to file structure based on 4-digit year and full name of month of photos creation date:<a class="headerlink" href="#export-photos-to-file-structure-based-on-4-digit-year-and-full-name-of-month-of-photo-s-creation-date" title="Permalink to this headline"></a></h4> <h4>export photos to file structure based on 4-digit year and full name of month of photos creation date:<a class="headerlink" href="#export-photos-to-file-structure-based-on-4-digit-year-and-full-name-of-month-of-photo-s-creation-date" title="Permalink to this headline"></a></h4>
<p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">export</span> <span class="pre">~/Desktop/export</span> <span class="pre">--directory</span> <span class="pre">&quot;{created.year}/{created.month}&quot;</span></code></p> <p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">export</span> <span class="pre">~/Desktop/export</span> <span class="pre">--directory</span> <span class="pre">&quot;{created.year}/{created.month}&quot;</span></code></p>
<p>(by default, it will attempt to use the system library)</p> <p>(by default, it will attempt to use the system library)</p>
</div> </section>
<div class="section" id="export-photos-to-file-structure-based-on-4-digit-year-of-photo-s-creation-date-and-add-keywords-for-media-type-and-labels-labels-are-only-awailable-on-photos-5-and-higher"> <section id="export-photos-to-file-structure-based-on-4-digit-year-of-photo-s-creation-date-and-add-keywords-for-media-type-and-labels-labels-are-only-awailable-on-photos-5-and-higher">
<h4>export photos to file structure based on 4-digit year of photos creation date and add keywords for media type and labels (labels are only awailable on Photos 5 and higher):<a class="headerlink" href="#export-photos-to-file-structure-based-on-4-digit-year-of-photo-s-creation-date-and-add-keywords-for-media-type-and-labels-labels-are-only-awailable-on-photos-5-and-higher" title="Permalink to this headline"></a></h4> <h4>export photos to file structure based on 4-digit year of photos creation date and add keywords for media type and labels (labels are only awailable on Photos 5 and higher):<a class="headerlink" href="#export-photos-to-file-structure-based-on-4-digit-year-of-photo-s-creation-date-and-add-keywords-for-media-type-and-labels-labels-are-only-awailable-on-photos-5-and-higher" title="Permalink to this headline"></a></h4>
<p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">export</span> <span class="pre">~/Desktop/export</span> <span class="pre">--directory</span> <span class="pre">&quot;{created.year}&quot;</span> <span class="pre">--keyword-template</span> <span class="pre">&quot;{label}&quot;</span> <span class="pre">--keyword-template</span> <span class="pre">&quot;{media_type}&quot;</span></code></p> <p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">export</span> <span class="pre">~/Desktop/export</span> <span class="pre">--directory</span> <span class="pre">&quot;{created.year}&quot;</span> <span class="pre">--keyword-template</span> <span class="pre">&quot;{label}&quot;</span> <span class="pre">--keyword-template</span> <span class="pre">&quot;{media_type}&quot;</span></code></p>
</div> </section>
<div class="section" id="export-default-library-using-country-name-year-as-output-directory-but-use-nocountry-year-if-country-not-specified-add-persons-album-names-and-year-as-keywords-write-exif-metadata-to-files-when-exporting-update-only-changed-files-print-verbose-ouput"> <section id="export-default-library-using-country-name-year-as-output-directory-but-use-nocountry-year-if-country-not-specified-add-persons-album-names-and-year-as-keywords-write-exif-metadata-to-files-when-exporting-update-only-changed-files-print-verbose-ouput">
<h4>export default library using country name/year as output directory (but use “NoCountry/year” if country not specified), add persons, album names, and year as keywords, write exif metadata to files when exporting, update only changed files, print verbose ouput<a class="headerlink" href="#export-default-library-using-country-name-year-as-output-directory-but-use-nocountry-year-if-country-not-specified-add-persons-album-names-and-year-as-keywords-write-exif-metadata-to-files-when-exporting-update-only-changed-files-print-verbose-ouput" title="Permalink to this headline"></a></h4> <h4>export default library using country name/year as output directory (but use “NoCountry/year” if country not specified), add persons, album names, and year as keywords, write exif metadata to files when exporting, update only changed files, print verbose ouput<a class="headerlink" href="#export-default-library-using-country-name-year-as-output-directory-but-use-nocountry-year-if-country-not-specified-add-persons-album-names-and-year-as-keywords-write-exif-metadata-to-files-when-exporting-update-only-changed-files-print-verbose-ouput" title="Permalink to this headline"></a></h4>
<p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">export</span> <span class="pre">~/Desktop/export</span> <span class="pre">--directory</span> <span class="pre">&quot;{place.name.country,NoCountry}/{created.year}&quot;</span>&#160; <span class="pre">--person-keyword</span> <span class="pre">--album-keyword</span> <span class="pre">--keyword-template</span> <span class="pre">&quot;{created.year}&quot;</span> <span class="pre">--exiftool</span> <span class="pre">--update</span> <span class="pre">--verbose</span></code></p> <p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">export</span> <span class="pre">~/Desktop/export</span> <span class="pre">--directory</span> <span class="pre">&quot;{place.name.country,NoCountry}/{created.year}&quot;</span>&#160; <span class="pre">--person-keyword</span> <span class="pre">--album-keyword</span> <span class="pre">--keyword-template</span> <span class="pre">&quot;{created.year}&quot;</span> <span class="pre">--exiftool</span> <span class="pre">--update</span> <span class="pre">--verbose</span></code></p>
</div> </section>
<div class="section" id="find-all-videos-larger-than-200mb-and-add-them-to-photos-album-big-videos-creating-the-album-if-necessary"> <section id="find-all-videos-larger-than-200mb-and-add-them-to-photos-album-big-videos-creating-the-album-if-necessary">
<h4>find all videos larger than 200MB and add them to Photos album “Big Videos” creating the album if necessary<a class="headerlink" href="#find-all-videos-larger-than-200mb-and-add-them-to-photos-album-big-videos-creating-the-album-if-necessary" title="Permalink to this headline"></a></h4> <h4>find all videos larger than 200MB and add them to Photos album “Big Videos” creating the album if necessary<a class="headerlink" href="#find-all-videos-larger-than-200mb-and-add-them-to-photos-album-big-videos-creating-the-album-if-necessary" title="Permalink to this headline"></a></h4>
<p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">query</span> <span class="pre">--only-movies</span> <span class="pre">--min-size</span> <span class="pre">200MB</span> <span class="pre">--add-to-album</span> <span class="pre">&quot;Big</span> <span class="pre">Videos&quot;</span></code></p> <p><code class="docutils literal notranslate"><span class="pre">osxphotos</span> <span class="pre">query</span> <span class="pre">--only-movies</span> <span class="pre">--min-size</span> <span class="pre">200MB</span> <span class="pre">--add-to-album</span> <span class="pre">&quot;Big</span> <span class="pre">Videos&quot;</span></code></p>
</div> </section>
</div> </section>
</div> </section>
<div class="section" id="example-uses-of-the-package"> <section id="example-uses-of-the-package">
<h2>Example uses of the package<a class="headerlink" href="#example-uses-of-the-package" title="Permalink to this headline"></a></h2> <h2>Example uses of the package<a class="headerlink" href="#example-uses-of-the-package" title="Permalink to this headline"></a></h2>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot; Simple usage of the package &quot;&quot;&quot;</span> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot; Simple usage of the package &quot;&quot;&quot;</span>
<span class="kn">import</span> <span class="nn">osxphotos</span> <span class="kn">import</span> <span class="nn">osxphotos</span>
@ -274,50 +275,29 @@ Alternatively, you can also run the command line utility like this: <code class=
<span class="n">export</span><span class="p">()</span> <span class="c1"># pylint: disable=no-value-for-parameter</span> <span class="n">export</span><span class="p">()</span> <span class="c1"># pylint: disable=no-value-for-parameter</span>
</pre></div> </pre></div>
</div> </div>
</div> </section>
<div class="section" id="package-interface"> <section id="package-interface">
<h2>Package Interface<a class="headerlink" href="#package-interface" title="Permalink to this headline"></a></h2> <h2>Package Interface<a class="headerlink" href="#package-interface" title="Permalink to this headline"></a></h2>
<p>Reference full documentation on <a class="reference external" href="https://github.com/RhetTbull/osxphotos/blob/master/README.md">GitHub</a></p> <p>Reference full documentation on <a class="reference external" href="https://github.com/RhetTbull/osxphotos/blob/master/README.md">GitHub</a></p>
<div class="toctree-wrapper compound"> <div class="toctree-wrapper compound">
<ul> <ul>
<li class="toctree-l1"><a class="reference internal" href="cli.html">osxphotos command line interface (CLI)</a><ul> <li class="toctree-l1"><a class="reference internal" href="cli.html">osxphotos command line interface (CLI)</a></li>
<li class="toctree-l2"><a class="reference internal" href="cli.html#osxphotos">osxphotos</a><ul>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-about">about</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-albums">albums</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-dump">dump</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-export">export</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-help">help</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-info">info</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-install">install</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-keywords">keywords</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-labels">labels</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-list">list</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-persons">persons</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-places">places</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-query">query</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-repl">repl</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-tutorial">tutorial</a></li>
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-uninstall">uninstall</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="reference.html">osxphotos package</a><ul> <li class="toctree-l1"><a class="reference internal" href="reference.html">osxphotos package</a><ul>
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos-module">osxphotos module</a></li> <li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos-module">osxphotos module</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </div>
</div> </section>
</div> </section>
<div class="section" id="indices-and-tables"> <section id="indices-and-tables">
<h1>Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this headline"></a></h1> <h1>Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this headline"></a></h1>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference internal" href="genindex.html"><span class="std std-ref">Index</span></a></p></li> <li><p><a class="reference internal" href="genindex.html"><span class="std std-ref">Index</span></a></p></li>
<li><p><a class="reference internal" href="py-modindex.html"><span class="std std-ref">Module Index</span></a></p></li> <li><p><a class="reference internal" href="py-modindex.html"><span class="std std-ref">Module Index</span></a></p></li>
<li><p><a class="reference internal" href="search.html"><span class="std std-ref">Search Page</span></a></p></li> <li><p><a class="reference internal" href="search.html"><span class="std std-ref">Search Page</span></a></p></li>
</ul> </ul>
</div> </section>
</div> </div>
@ -375,7 +355,7 @@ Alternatively, you can also run the command line utility like this: <code class=
&copy;2021, Rhet Turnbull. &copy;2021, Rhet Turnbull.
| |
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.3.2</a> Powered by <a href="http://sphinx-doc.org/">Sphinx 4.3.1</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a> &amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
| |

View File

@ -4,8 +4,9 @@
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>osxphotos &#8212; osxphotos 0.43.9 documentation</title>
<title>osxphotos &#8212; osxphotos 0.44.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" /> <link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script> <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
@ -30,11 +31,11 @@
<div class="body" role="main"> <div class="body" role="main">
<div class="section" id="osxphotos"> <section id="osxphotos">
<h1>osxphotos<a class="headerlink" href="#osxphotos" title="Permalink to this headline"></a></h1> <h1>osxphotos<a class="headerlink" href="#osxphotos" title="Permalink to this headline"></a></h1>
<div class="toctree-wrapper compound"> <div class="toctree-wrapper compound">
</div> </div>
</div> </section>
</div> </div>
@ -91,7 +92,7 @@
&copy;2021, Rhet Turnbull. &copy;2021, Rhet Turnbull.
| |
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.3.2</a> Powered by <a href="http://sphinx-doc.org/">Sphinx 4.3.1</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a> &amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
| |

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Search &#8212; osxphotos 0.43.9 documentation</title> <title>Search &#8212; osxphotos 0.44.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" /> <link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
@ -111,7 +111,7 @@
&copy;2021, Rhet Turnbull. &copy;2021, Rhet Turnbull.
| |
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.3.2</a> Powered by <a href="http://sphinx-doc.org/">Sphinx 4.3.1</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a> &amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
</div> </div>

File diff suppressed because one or more lines are too long

View File

@ -123,12 +123,20 @@ _XMP_TEMPLATE_NAME_BETA = "xmp_sidecar_beta.mako"
# Constants used for processing folders and albums # Constants used for processing folders and albums
_PHOTOS_5_ALBUM_KIND = 2 # normal user album _PHOTOS_5_ALBUM_KIND = 2 # normal user album
_PHOTOS_5_SHARED_ALBUM_KIND = 1505 # shared album _PHOTOS_5_SHARED_ALBUM_KIND = 1505 # shared album
_PHOTOS_5_PROJECT_ALBUM_KIND = 1508 # My Projects (e.g. Calendar, Card, Slideshow)
_PHOTOS_5_FOLDER_KIND = 4000 # user folder _PHOTOS_5_FOLDER_KIND = 4000 # user folder
_PHOTOS_5_ROOT_FOLDER_KIND = 3999 # root folder _PHOTOS_5_ROOT_FOLDER_KIND = 3999 # root folder
_PHOTOS_5_IMPORT_SESSION_ALBUM_KIND = 1506 # import session _PHOTOS_5_IMPORT_SESSION_ALBUM_KIND = 1506 # import session
_PHOTOS_4_ALBUM_KIND = 3 # RKAlbum.albumSubclass _PHOTOS_4_ALBUM_KIND = 3 # RKAlbum.albumSubclass
_PHOTOS_4_TOP_LEVEL_ALBUM = "TopLevelAlbums" _PHOTOS_4_ALBUM_TYPE_ALBUM = 1 # RKAlbum.albumType
_PHOTOS_4_ALBUM_TYPE_PROJECT = 9 # RKAlbum.albumType
_PHOTOS_4_ALBUM_TYPE_SLIDESHOW = 8 # RKAlbum.albumType
_PHOTOS_4_TOP_LEVEL_ALBUMS = [
"TopLevelAlbums",
"TopLevelKeepsakes",
"TopLevelSlideshows",
]
_PHOTOS_4_ROOT_FOLDER = "LibraryFolder" _PHOTOS_4_ROOT_FOLDER = "LibraryFolder"
# EXIF related constants # EXIF related constants

View File

@ -1,3 +1,3 @@
""" version info """ """ version info """
__version__ = "0.43.9" __version__ = "0.44.0"

View File

@ -14,7 +14,7 @@ from datetime import datetime, timedelta, timezone
from ._constants import ( from ._constants import (
_PHOTOS_4_ALBUM_KIND, _PHOTOS_4_ALBUM_KIND,
_PHOTOS_4_TOP_LEVEL_ALBUM, _PHOTOS_4_TOP_LEVEL_ALBUMS,
_PHOTOS_4_VERSION, _PHOTOS_4_VERSION,
_PHOTOS_5_ALBUM_KIND, _PHOTOS_5_ALBUM_KIND,
_PHOTOS_5_FOLDER_KIND, _PHOTOS_5_FOLDER_KIND,
@ -161,7 +161,6 @@ class AlbumInfoBaseClass:
class AlbumInfo(AlbumInfoBaseClass): class AlbumInfo(AlbumInfoBaseClass):
""" """
Base class for AlbumInfo, ImportInfo
Info about a specific Album, contains all the details about the album Info about a specific Album, contains all the details about the album
including folders, photos, etc. including folders, photos, etc.
""" """
@ -231,7 +230,7 @@ class AlbumInfo(AlbumInfoBaseClass):
parent_uuid = self._db._dbalbum_details[self._uuid]["folderUuid"] parent_uuid = self._db._dbalbum_details[self._uuid]["folderUuid"]
self._parent = ( self._parent = (
FolderInfo(db=self._db, uuid=parent_uuid) FolderInfo(db=self._db, uuid=parent_uuid)
if parent_uuid != _PHOTOS_4_TOP_LEVEL_ALBUM if parent_uuid not in _PHOTOS_4_TOP_LEVEL_ALBUMS
else None else None
) )
else: else:
@ -266,18 +265,17 @@ class AlbumInfo(AlbumInfoBaseClass):
def photo_index(self, photo): def photo_index(self, photo):
"""return index of photo in album (based on album sort order)""" """return index of photo in album (based on album sort order)"""
index = 0 for index, p in enumerate(self.photos):
for p in self.photos:
if p.uuid == photo.uuid: if p.uuid == photo.uuid:
return index return index
index += 1
else:
raise ValueError( raise ValueError(
f"Photo with uuid {photo.uuid} does not appear to be in this album" f"Photo with uuid {photo.uuid} does not appear to be in this album"
) )
class ImportInfo(AlbumInfoBaseClass): class ImportInfo(AlbumInfoBaseClass):
"""Information about import sessions"""
@property @property
def photos(self): def photos(self):
"""return list of photos contained in import session""" """return list of photos contained in import session"""
@ -296,6 +294,15 @@ class ImportInfo(AlbumInfoBaseClass):
return self._photos return self._photos
class ProjectInfo(AlbumInfo):
"""
ProjectInfo with info about projects
Projects are cards, calendars, slideshows, etc.
"""
...
class FolderInfo: class FolderInfo:
""" """
Info about a specific folder, contains all the details about the folder Info about a specific folder, contains all the details about the folder
@ -357,7 +364,7 @@ class FolderInfo:
parent_uuid = self._db._dbfolder_details[self._uuid]["parentFolderUuid"] parent_uuid = self._db._dbfolder_details[self._uuid]["parentFolderUuid"]
self._parent = ( self._parent = (
FolderInfo(db=self._db, uuid=parent_uuid) FolderInfo(db=self._db, uuid=parent_uuid)
if parent_uuid != _PHOTOS_4_TOP_LEVEL_ALBUM if parent_uuid not in _PHOTOS_4_TOP_LEVEL_ALBUMS
else None else None
) )
else: else:

View File

@ -4159,6 +4159,7 @@ def _spotlight_photo(photo: PhotoInfo):
) )
def repl(ctx, cli_obj, db, emacs): def repl(ctx, cli_obj, db, emacs):
"""Run interactive osxphotos REPL shell (useful for debugging, prototyping, and inspecting your Photos library)""" """Run interactive osxphotos REPL shell (useful for debugging, prototyping, and inspecting your Photos library)"""
import logging
from objexplore import explore from objexplore import explore
from photoscript import Album, Photo, PhotosLibrary from photoscript import Album, Photo, PhotosLibrary
@ -4169,6 +4170,9 @@ def repl(ctx, cli_obj, db, emacs):
from osxphotos.placeinfo import PlaceInfo from osxphotos.placeinfo import PlaceInfo
from osxphotos.queryoptions import QueryOptions from osxphotos.queryoptions import QueryOptions
logger = logging.getLogger()
logger.disabled = True
pretty.install() pretty.install()
print(f"python version: {sys.version}") print(f"python version: {sys.version}")
print(f"osxphotos version: {osxphotos._version.__version__}") print(f"osxphotos version: {osxphotos._version.__version__}")

View File

@ -20,10 +20,14 @@ from .._constants import (
_MOVIE_TYPE, _MOVIE_TYPE,
_PHOTO_TYPE, _PHOTO_TYPE,
_PHOTOS_4_ALBUM_KIND, _PHOTOS_4_ALBUM_KIND,
_PHOTOS_4_ALBUM_TYPE_ALBUM,
_PHOTOS_4_ALBUM_TYPE_PROJECT,
_PHOTOS_4_ALBUM_TYPE_SLIDESHOW,
_PHOTOS_4_ROOT_FOLDER, _PHOTOS_4_ROOT_FOLDER,
_PHOTOS_4_VERSION, _PHOTOS_4_VERSION,
_PHOTOS_5_ALBUM_KIND, _PHOTOS_5_ALBUM_KIND,
_PHOTOS_5_IMPORT_SESSION_ALBUM_KIND, _PHOTOS_5_IMPORT_SESSION_ALBUM_KIND,
_PHOTOS_5_PROJECT_ALBUM_KIND,
_PHOTOS_5_SHARED_ALBUM_KIND, _PHOTOS_5_SHARED_ALBUM_KIND,
_PHOTOS_5_SHARED_PHOTO_PATH, _PHOTOS_5_SHARED_PHOTO_PATH,
_PHOTOS_5_VERSION, _PHOTOS_5_VERSION,
@ -34,7 +38,7 @@ from .._constants import (
TEXT_DETECTION_CONFIDENCE_THRESHOLD, TEXT_DETECTION_CONFIDENCE_THRESHOLD,
) )
from ..adjustmentsinfo import AdjustmentsInfo from ..adjustmentsinfo import AdjustmentsInfo
from ..albuminfo import AlbumInfo, ImportInfo from ..albuminfo import AlbumInfo, ImportInfo, ProjectInfo
from ..momentinfo import MomentInfo from ..momentinfo import MomentInfo
from ..personinfo import FaceInfo, PersonInfo from ..personinfo import FaceInfo, PersonInfo
from ..phototemplate import PhotoTemplate, RenderOptions from ..phototemplate import PhotoTemplate, RenderOptions
@ -570,6 +574,18 @@ class PhotoInfo:
) )
return self._import_info return self._import_info
@property
def project_info(self):
"""list of AlbumInfo objects representing projects for the photo or None if no projects"""
try:
return self._project_info
except AttributeError:
project_uuids = self._get_album_uuids(project=True)
self._project_info = [
ProjectInfo(db=self._db, uuid=album) for album in project_uuids
]
return self._project_info
@property @property
def keywords(self): def keywords(self):
"""list of keywords for picture""" """list of keywords for picture"""
@ -1197,37 +1213,51 @@ class PhotoInfo:
"""Returns latitude, in degrees""" """Returns latitude, in degrees"""
return self._info["latitude"] return self._info["latitude"]
def _get_album_uuids(self): def _get_album_uuids(self, project=False):
"""Return list of album UUIDs this photo is found in """Return list of album UUIDs this photo is found in
Filters out albums in the trash and any special album types Filters out albums in the trash and any special album types
if project is True, returns special "My Project" albums (e.g. cards, calendars, slideshows)
Returns: list of album UUIDs Returns: list of album UUIDs
""" """
if self._db._db_version <= _PHOTOS_4_VERSION: if self._db._db_version <= _PHOTOS_4_VERSION:
version4 = True
album_kind = [_PHOTOS_4_ALBUM_KIND] album_kind = [_PHOTOS_4_ALBUM_KIND]
else: album_type = (
version4 = False [_PHOTOS_4_ALBUM_TYPE_PROJECT, _PHOTOS_4_ALBUM_TYPE_SLIDESHOW]
album_kind = [_PHOTOS_5_SHARED_ALBUM_KIND, _PHOTOS_5_ALBUM_KIND] if project
else [_PHOTOS_4_ALBUM_TYPE_ALBUM]
)
album_list = [] album_list = []
for album in self._info["albums"]: for album in self._info["albums"]:
detail = self._db._dbalbum_details[album] detail = self._db._dbalbum_details[album]
if ( if (
detail["kind"] in album_kind detail["kind"] in album_kind
and detail["albumType"] in album_type
and not detail["intrash"] and not detail["intrash"]
and ( and detail["folderUuid"] != _PHOTOS_4_ROOT_FOLDER
not version4
# in Photos <= 4, special albums like "printAlbum" have kind _PHOTOS_4_ALBUM_KIND # in Photos <= 4, special albums like "printAlbum" have kind _PHOTOS_4_ALBUM_KIND
# but should not be listed here; they can be distinguished by looking # but should not be listed here; they can be distinguished by looking
# for folderUuid of _PHOTOS_4_ROOT_FOLDER as opposed to _PHOTOS_4_TOP_LEVEL_ALBUM # for folderUuid of _PHOTOS_4_ROOT_FOLDER as opposed to _PHOTOS_4_TOP_LEVEL_ALBUM
or (version4 and detail["folderUuid"] != _PHOTOS_4_ROOT_FOLDER)
)
): ):
album_list.append(album) album_list.append(album)
return album_list return album_list
# Photos 5+
album_kind = (
[_PHOTOS_5_PROJECT_ALBUM_KIND]
if project
else [_PHOTOS_5_SHARED_ALBUM_KIND, _PHOTOS_5_ALBUM_KIND]
)
album_list = []
for album in self._info["albums"]:
detail = self._db._dbalbum_details[album]
if detail["kind"] in album_kind and not detail["intrash"]:
album_list.append(album)
return album_list
def __repr__(self): def __repr__(self):
return f"osxphotos.{self.__class__.__name__}(db={self._db}, uuid='{self._uuid}', info={self._info})" return f"osxphotos.{self.__class__.__name__}(db={self._db}, uuid='{self._uuid}', info={self._info})"

View File

@ -28,11 +28,15 @@ from .._constants import (
_PHOTOS_3_VERSION, _PHOTOS_3_VERSION,
_PHOTOS_4_ALBUM_KIND, _PHOTOS_4_ALBUM_KIND,
_PHOTOS_4_ROOT_FOLDER, _PHOTOS_4_ROOT_FOLDER,
_PHOTOS_4_TOP_LEVEL_ALBUM, _PHOTOS_4_TOP_LEVEL_ALBUMS,
_PHOTOS_4_ALBUM_TYPE_ALBUM,
_PHOTOS_4_ALBUM_TYPE_PROJECT,
_PHOTOS_4_ALBUM_TYPE_SLIDESHOW,
_PHOTOS_4_VERSION, _PHOTOS_4_VERSION,
_PHOTOS_5_ALBUM_KIND, _PHOTOS_5_ALBUM_KIND,
_PHOTOS_5_FOLDER_KIND, _PHOTOS_5_FOLDER_KIND,
_PHOTOS_5_IMPORT_SESSION_ALBUM_KIND, _PHOTOS_5_IMPORT_SESSION_ALBUM_KIND,
_PHOTOS_5_PROJECT_ALBUM_KIND,
_PHOTOS_5_ROOT_FOLDER_KIND, _PHOTOS_5_ROOT_FOLDER_KIND,
_PHOTOS_5_SHARED_ALBUM_KIND, _PHOTOS_5_SHARED_ALBUM_KIND,
_TESTED_OS_VERSIONS, _TESTED_OS_VERSIONS,
@ -42,7 +46,7 @@ from .._constants import (
TIME_DELTA, TIME_DELTA,
) )
from .._version import __version__ from .._version import __version__
from ..albuminfo import AlbumInfo, FolderInfo, ImportInfo from ..albuminfo import AlbumInfo, FolderInfo, ImportInfo, ProjectInfo
from ..datetime_utils import datetime_has_tz, datetime_naive_to_local from ..datetime_utils import datetime_has_tz, datetime_naive_to_local
from ..fileutil import FileUtil from ..fileutil import FileUtil
from ..personinfo import PersonInfo from ..personinfo import PersonInfo
@ -429,7 +433,7 @@ class PhotosDB:
for folder, detail in self._dbfolder_details.items() for folder, detail in self._dbfolder_details.items()
if not detail["intrash"] if not detail["intrash"]
and not detail["isMagic"] and not detail["isMagic"]
and detail["parentFolderUuid"] == _PHOTOS_4_TOP_LEVEL_ALBUM and detail["parentFolderUuid"] in _PHOTOS_4_TOP_LEVEL_ALBUMS
] ]
else: else:
folders = [ folders = [
@ -450,7 +454,7 @@ class PhotosDB:
for folder in self._dbfolder_details.values() for folder in self._dbfolder_details.values()
if not folder["intrash"] if not folder["intrash"]
and not folder["isMagic"] and not folder["isMagic"]
and folder["parentFolderUuid"] == _PHOTOS_4_TOP_LEVEL_ALBUM and folder["parentFolderUuid"] in _PHOTOS_4_TOP_LEVEL_ALBUMS
] ]
else: else:
folder_names = [ folder_names = [
@ -529,6 +533,18 @@ class PhotosDB:
] ]
return self._import_info return self._import_info
@property
def project_info(self):
"""return list of AlbumInfo projects for each project in the database"""
try:
return self._project_info
except AttributeError:
self._project_info = [
ProjectInfo(db=self, uuid=album)
for album in self._get_album_uuids(project=True)
]
return self._project_info
@property @property
def db_version(self): def db_version(self):
"""return the database version as stored in LiGlobals table""" """return the database version as stored in LiGlobals table"""
@ -848,11 +864,10 @@ class PhotosDB:
# build folder hierarchy # build folder hierarchy
for album, details in self._dbalbum_details.items(): for album, details in self._dbalbum_details.items():
parent_folder = details["folderUuid"] parent_folder = details["folderUuid"]
if details[ if (
"albumSubclass" details["albumSubclass"] == _PHOTOS_4_ALBUM_KIND
] == _PHOTOS_4_ALBUM_KIND and parent_folder not in [ and parent_folder not in _PHOTOS_4_TOP_LEVEL_ALBUMS
_PHOTOS_4_TOP_LEVEL_ALBUM ):
]:
folder_hierarchy = self._build_album_folder_hierarchy_4(parent_folder) folder_hierarchy = self._build_album_folder_hierarchy_4(parent_folder)
self._dbalbum_folders[album] = folder_hierarchy self._dbalbum_folders[album] = folder_hierarchy
else: else:
@ -1582,7 +1597,7 @@ class PhotosDB:
if parent_uuid is None: if parent_uuid is None:
return folders return folders
if parent_uuid == _PHOTOS_4_TOP_LEVEL_ALBUM: if parent_uuid in _PHOTOS_4_TOP_LEVEL_ALBUMS:
if not folders: if not folders:
# this is a top-level folder with no sub-folders # this is a top-level folder with no sub-folders
folders = {uuid: None} folders = {uuid: None}
@ -2825,7 +2840,7 @@ class PhotosDB:
hierarchy = _recurse_folder_hierarchy(folders) hierarchy = _recurse_folder_hierarchy(folders)
return hierarchy return hierarchy
def _get_album_uuids(self, shared=False, import_session=False): def _get_album_uuids(self, shared=False, import_session=False, project=False):
"""Return list of album UUIDs found in photos database """Return list of album UUIDs found in photos database
Filters out albums in the trash and any special album types Filters out albums in the trash and any special album types
@ -2833,20 +2848,21 @@ class PhotosDB:
Args: Args:
shared: boolean; if True, returns shared albums, else normal albums shared: boolean; if True, returns shared albums, else normal albums
import_session: boolean, if True, returns import session albums, else normal or shared albums import_session: boolean, if True, returns import session albums, else normal or shared albums
project: boolean, if True, returns albums that are part of My Projects
Note: flags (shared, import_session) are mutually exclusive Note: flags (shared, import_session) are mutually exclusive
Raises: Raises:
ValueError: raised if mutually exclusive flags passed ValueError: raised if mutually exclusive flags passed
Returns: list of album UUIDs Returns: list of album UUIDs
""" """
if shared and import_session: if sum(bool(x) for x in [shared, import_session, project]) > 1:
raise ValueError( raise ValueError(
"flags are mutually exclusive: pass zero or one of shared, import_session" "flags are mutually exclusive: pass zero or one of shared, import_session, projects"
) )
if self._db_version <= _PHOTOS_4_VERSION: if self._db_version <= _PHOTOS_4_VERSION:
version4 = True
if shared: if shared:
logging.warning( logging.warning(
f"Shared albums not implemented for Photos library version {self._db_version}" f"Shared albums not implemented for Photos library version {self._db_version}"
@ -2857,14 +2873,42 @@ class PhotosDB:
f"Import sessions not implemented for Photos library version {self._db_version}" f"Import sessions not implemented for Photos library version {self._db_version}"
) )
return [] # not implemented for _PHOTOS_4_VERSION return [] # not implemented for _PHOTOS_4_VERSION
else: elif project:
album_type = [
_PHOTOS_4_ALBUM_TYPE_PROJECT,
_PHOTOS_4_ALBUM_TYPE_SLIDESHOW,
]
album_kind = _PHOTOS_4_ALBUM_KIND album_kind = _PHOTOS_4_ALBUM_KIND
else: else:
version4 = False album_type = [_PHOTOS_4_ALBUM_TYPE_ALBUM]
album_kind = _PHOTOS_4_ALBUM_KIND
album_list = []
# look through _dbalbum_details because _dbalbums_album won't have empty albums it
for album, detail in self._dbalbum_details.items():
if (
detail["kind"] == album_kind
and detail["albumType"] in album_type
and not detail["intrash"]
and (
(shared and detail["cloudownerhashedpersonid"] is not None)
or (not shared and detail["cloudownerhashedpersonid"] is None)
)
and detail["folderUuid"] != _PHOTOS_4_ROOT_FOLDER
# in Photos <= 4, special albums like "printAlbum" have kind _PHOTOS_4_ALBUM_KIND
# but should not be listed here; they can be distinguished by looking
# for folderUuid of _PHOTOS_4_ROOT_FOLDER as opposed to _PHOTOS_4_TOP_LEVEL_ALBUM
):
album_list.append(album)
return album_list
# Photos version 5+
if shared: if shared:
album_kind = _PHOTOS_5_SHARED_ALBUM_KIND album_kind = _PHOTOS_5_SHARED_ALBUM_KIND
elif import_session: elif import_session:
album_kind = _PHOTOS_5_IMPORT_SESSION_ALBUM_KIND album_kind = _PHOTOS_5_IMPORT_SESSION_ALBUM_KIND
elif project:
album_kind = _PHOTOS_5_PROJECT_ALBUM_KIND
else: else:
album_kind = _PHOTOS_5_ALBUM_KIND album_kind = _PHOTOS_5_ALBUM_KIND
@ -2878,13 +2922,6 @@ class PhotosDB:
(shared and detail["cloudownerhashedpersonid"] is not None) (shared and detail["cloudownerhashedpersonid"] is not None)
or (not shared and detail["cloudownerhashedpersonid"] is None) or (not shared and detail["cloudownerhashedpersonid"] is None)
) )
and (
not version4
# in Photos 4, special albums like "printAlbum" have kind _PHOTOS_4_ALBUM_KIND
# but should not be listed here; they can be distinguished by looking
# for folderUuid of _PHOTOS_4_ROOT_FOLDER as opposed to _PHOTOS_4_TOP_LEVEL_ALBUM
or (version4 and detail["folderUuid"] != _PHOTOS_4_ROOT_FOLDER)
)
): ):
album_list.append(album) album_list.append(album)
return album_list return album_list

View File

@ -181,6 +181,9 @@ TEMPLATE_SUBSTITUTIONS_PATHLIB = {
TEMPLATE_SUBSTITUTIONS_MULTI_VALUED = { TEMPLATE_SUBSTITUTIONS_MULTI_VALUED = {
"{album}": "Album(s) photo is contained in", "{album}": "Album(s) photo is contained in",
"{folder_album}": "Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder", "{folder_album}": "Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder",
"{project}": "Project(s) photo is contained in (such as greeting cards, calendars, slideshows)",
"{album_project}": "Album(s) and project(s) photo is contained in; treats projects as regular albums",
"{folder_album_project}": "Folder path + album (includes projects as albums) photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder",
"{keyword}": "Keyword(s) assigned to photo", "{keyword}": "Keyword(s) assigned to photo",
"{person}": "Person(s) / face(s) in a photo", "{person}": "Person(s) / face(s) in a photo",
"{label}": "Image categorization label associated with a photo (Photos 5+ only). " "{label}": "Image categorization label associated with a photo (Photos 5+ only). "
@ -1116,6 +1119,11 @@ class PhotoTemplate:
values = [] values = []
if field == "album": if field == "album":
values = self.photo.burst_albums if self.photo.burst else self.photo.albums values = self.photo.burst_albums if self.photo.burst else self.photo.albums
elif field == "project":
values = [p.title for p in self.photo.project_info]
elif field == "album_project":
values = self.photo.burst_albums if self.photo.burst else self.photo.albums
values += [p.title for p in self.photo.project_info]
elif field == "keyword": elif field == "keyword":
values = self.photo.keywords values = self.photo.keywords
elif field == "person": elif field == "person":
@ -1126,13 +1134,15 @@ class PhotoTemplate:
values = self.photo.labels values = self.photo.labels
elif field == "label_normalized": elif field == "label_normalized":
values = self.photo.labels_normalized values = self.photo.labels_normalized
elif field == "folder_album": elif field in ["folder_album", "folder_album_project"]:
values = [] values = []
# photos must be in an album to be in a folder # photos must be in an album to be in a folder
if self.photo.burst: if self.photo.burst:
album_info = self.photo.burst_album_info album_info = self.photo.burst_album_info
else: else:
album_info = self.photo.album_info album_info = self.photo.album_info
if field == "folder_album_project":
album_info += self.photo.project_info
for album in album_info: for album in album_info:
if album.folder_names: if album.folder_names:
# album in folder # album in folder
@ -1193,7 +1203,7 @@ class PhotoTemplate:
elif isinstance(obj, (str, int, float)): elif isinstance(obj, (str, int, float)):
values = [str(obj)] values = [str(obj)]
else: else:
values = [val for val in obj] values = list(obj)
elif field == "detected_text": elif field == "detected_text":
values = _get_detected_text(self.photo, self.exportdb, confidence=subfield) values = _get_detected_text(self.photo, self.exportdb, confidence=subfield)
else: else:

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 504 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -0,0 +1,12 @@
<?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>MajorVersion</key>
<integer>1</integer>
<key>MinorVersion</key>
<integer>34</integer>
<key>createDate</key>
<date>2021-12-30T03:56:43Z</date>
</dict>
</plist>

View File

@ -0,0 +1,20 @@
<?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>DatabaseMinorVersion</key>
<integer>1</integer>
<key>DatabaseVersion</key>
<integer>112</integer>
<key>LastOpenMode</key>
<integer>2</integer>
<key>LibrarySchemaVersion</key>
<integer>2622</integer>
<key>MetaSchemaVersion</key>
<integer>2</integer>
<key>createDate</key>
<date>2021-12-29T18:15:21Z</date>
<key>databaseUuid</key>
<string>Nm7MKBmoSRygMmA9WlEaGw</string>
</dict>
</plist>

View File

@ -0,0 +1,27 @@
<?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>LithiumMessageTracer</key>
<dict>
<key>LastReportedDate</key>
<date>2021-12-30T03:56:48Z</date>
</dict>
<key>PXPeopleScreenUnlocked</key>
<true/>
<key>Photos</key>
<dict>
<key>IPXWorkspaceControllerZoomLevelsKey</key>
<dict>
<key>kZoomLevelIdentifierAlbums</key>
<integer>7</integer>
<key>kZoomLevelIdentifierVersions</key>
<integer>7</integer>
</dict>
</dict>
<key>RDLegacyProxyMediaRelocationCleanupCompletedKey</key>
<true/>
<key>ShowHiddenPhotosAlbumUserDefault</key>
<true/>
</dict>
</plist>

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>PhotoAnalysisGraphLastBackgroundGraphRebuildJobDate</key>
<date>2021-12-31T04:32:23Z</date>
<key>PhotoAnalysisGraphLastBackgroundMemoryGenerationJobDate</key>
<date>2021-12-31T04:32:23Z</date>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

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>PLLanguageAndLocaleKey</key>
<string>en-US:en_US</string>
<key>PLLastGeoProviderIdKey</key>
<string>7618</string>
<key>PLLastLocationInfoFormatVer</key>
<integer>12</integer>
<key>PLLastRevGeoForcedProviderOutOfDateCheckVersionKey</key>
<integer>1</integer>
<key>PLLastRevGeoVerFileFetchDateKey</key>
<date>2021-12-30T03:56:45Z</date>
</dict>
</plist>

View File

@ -0,0 +1,12 @@
<?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>LastHistoryRowId</key>
<integer>164</integer>
<key>LibraryBuildTag</key>
<string>E371079C-71D9-4C33-91F6-54B17B4B3066</string>
<key>LibrarySchemaVersion</key>
<integer>2622</integer>
</dict>
</plist>

View File

@ -0,0 +1,47 @@
<?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>FileVersion</key>
<integer>11</integer>
<key>Source</key>
<dict>
<key>35230</key>
<dict>
<key>CountryMinVersions</key>
<dict>
<key>OTHER</key>
<integer>1</integer>
</dict>
<key>CurrentVersion</key>
<integer>1</integer>
<key>NoResultErrorIsSuccess</key>
<true/>
</dict>
<key>57879</key>
<dict>
<key>CountryMinVersions</key>
<dict>
<key>OTHER</key>
<integer>1</integer>
</dict>
<key>CurrentVersion</key>
<integer>1</integer>
<key>NoResultErrorIsSuccess</key>
<true/>
</dict>
<key>7618</key>
<dict>
<key>AddCountyIfNeeded</key>
<true/>
<key>CountryMinVersions</key>
<dict>
<key>OTHER</key>
<integer>10</integer>
</dict>
<key>CurrentVersion</key>
<integer>10</integer>
</dict>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,12 @@
<?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>MajorVersion</key>
<integer>1</integer>
<key>MinorVersion</key>
<integer>34</integer>
<key>createDate</key>
<date>2021-12-30T03:56:43Z</date>
</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>creationDate</key>
<date>2021-12-30T03:56:00Z</date>
<key>name</key>
<string>Photos</string>
<key>previewImageHash</key>
<integer>0</integer>
<key>previewImageName</key>
<string>Calendar</string>
<key>themeIdentifier</key>
<string>Picture-Calendar</string>
<key>type</key>
<integer>2</integer>
</dict>
</plist>

View File

@ -0,0 +1,12 @@
<?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>MajorVersion</key>
<integer>1</integer>
<key>MinorVersion</key>
<integer>34</integer>
<key>createDate</key>
<date>2021-12-30T03:56:43Z</date>
</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>creationDate</key>
<date>2021-12-30T03:55:08Z</date>
<key>name</key>
<string>Photos</string>
<key>previewImageHash</key>
<integer>0</integer>
<key>previewImageName</key>
<string>Card_Landscape</string>
<key>themeIdentifier</key>
<string>PremiumClassic-FoldedCard</string>
<key>type</key>
<integer>1</integer>
</dict>
</plist>

View File

@ -0,0 +1,112 @@
<?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>DatabaseMinorVersion</key>
<integer>1</integer>
<key>DatabaseVersion</key>
<integer>112</integer>
<key>HistoricalMarker</key>
<dict>
<key>LastHistoryRowId</key>
<integer>164</integer>
<key>LibraryBuildTag</key>
<string>E371079C-71D9-4C33-91F6-54B17B4B3066</string>
<key>LibrarySchemaVersion</key>
<integer>2622</integer>
</dict>
<key>LibrarySchemaVersion</key>
<integer>2622</integer>
<key>MetaSchemaVersion</key>
<integer>2</integer>
<key>SnapshotComplete</key>
<true/>
<key>SnapshotCompletedDate</key>
<date>2021-12-30T03:56:44Z</date>
<key>SnapshotLastAttemptStartDate</key>
<date>2021-12-30T03:56:44Z</date>
<key>SnapshotTables</key>
<dict>
<key>RKAdminData</key>
<dict>
<key>0000000000.lisj</key>
<string>33ba9a656c3588b4bdc1e44575e794e1d256d625</string>
</dict>
<key>RKAlbum</key>
<dict>
<key>0000000000.lisj</key>
<string>3b09c246d3a74e7f57265e6ab6abb0d333665215</string>
</dict>
<key>RKAlbumVersion</key>
<dict>
<key>0000000000.lisj</key>
<string>fc7c9baa656623406304fcc10474e561dff5a53a</string>
</dict>
<key>RKBookmark</key>
<dict>
<key>0000000000.lisj</key>
<string>33e3f9220c22909667ab63c0070757b8ffe1aeac</string>
</dict>
<key>RKCustomSortOrder</key>
<dict>
<key>0000000000.lisj</key>
<string>d65281f0c3f9e519cc5a00e21bb5ece35aa03cbd</string>
</dict>
<key>RKFace</key>
<dict>
<key>0000000000.lisj</key>
<string>dd0f12962d72c2e53f483bd3e02e18f3bbf423ac</string>
</dict>
<key>RKFolder</key>
<dict>
<key>0000000000.lisj</key>
<string>8712074c0728e02c777705031c0e16882eda9bff</string>
</dict>
<key>RKImageProxyState</key>
<dict>
<key>0000000000.lisj</key>
<string>5b0f369a4df955c63b1a636980e76e3d30d99fa9</string>
</dict>
<key>RKImportGroup</key>
<dict>
<key>0000000000.lisj</key>
<string>0ad244b52516a1cac3ea5532af1e60b3f74b4af7</string>
</dict>
<key>RKKeyword</key>
<dict>
<key>0000000000.lisj</key>
<string>85669e2bf25048d655ed8042d1607d50587de1fc</string>
</dict>
<key>RKKeywordForVersion</key>
<dict>
<key>0000000000.lisj</key>
<string>cf61584fa6191e45a64311ae4617418fde4d5263</string>
</dict>
<key>RKMaster</key>
<dict>
<key>0000000000.lisj</key>
<string>a609e1942bd9e5d69f3532e1e3e091156f5c3469</string>
</dict>
<key>RKModelResource</key>
<dict>
<key>0000000000.lisj</key>
<string>c677e8613d841620d96ed750d1a720bd283a0df7</string>
</dict>
<key>RKVersion</key>
<dict>
<key>0000000000.lisj</key>
<string>b2d209286b8f7b68a5fba0fb84e364ce55d83608</string>
</dict>
<key>RKVersionAnalysisState</key>
<dict>
<key>0000000000.lisj</key>
<string>2a36598c306df54e303c14ccb19bcdeae2d85bf5</string>
</dict>
<key>RKVolume</key>
<dict>
<key>0000000000.lisj</key>
<string>5d16bc7903a060b2e879d148100441b1ac5c1629</string>
</dict>
</dict>
</dict>
</plist>

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