Compare commits
17 Commits
multiproce
...
v0.46.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b92a681795 | ||
|
|
1941e79d21 | ||
|
|
5290fae2e0 | ||
|
|
ecbd370a47 | ||
|
|
d8204e65eb | ||
|
|
9c26e5519b | ||
|
|
060729c4c4 | ||
|
|
65d51ab129 | ||
|
|
afbda030bc | ||
|
|
d111d07fb7 | ||
|
|
30abdddaf3 | ||
|
|
a2f329b8de | ||
|
|
bfa888adc5 | ||
|
|
ac4083bfbb | ||
|
|
5fb686ac0c | ||
|
|
49a7b80680 | ||
|
|
cb11967eac |
36
CHANGELOG.md
36
CHANGELOG.md
@@ -4,6 +4,42 @@ 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.46.0](https://github.com/RhetTbull/osxphotos/compare/v0.45.12...v0.46.0)
|
||||
|
||||
> 21 February 2022
|
||||
|
||||
- Exportdb refactor [`#638`](https://github.com/RhetTbull/osxphotos/pull/638)
|
||||
- Updated docs [skip ci] [`5290fae`](https://github.com/RhetTbull/osxphotos/commit/5290fae2e0ad062750348aedfee4feaf7b2e769f)
|
||||
|
||||
#### [v0.45.12](https://github.com/RhetTbull/osxphotos/compare/v0.45.11...v0.45.12)
|
||||
|
||||
> 14 February 2022
|
||||
|
||||
- Allow multiple characters as path_sep, #634 [`d8204e6`](https://github.com/RhetTbull/osxphotos/commit/d8204e65eb740cece468ef021cbdf45d896d954e)
|
||||
- Added --debug and crash reporter to export, #628 [`060729c`](https://github.com/RhetTbull/osxphotos/commit/060729c4c4255651c6ee8149989d9de541d0a6aa)
|
||||
- Added crash_reporter.py [`9c26e55`](https://github.com/RhetTbull/osxphotos/commit/9c26e5519b2d48f3a0ae80d1cc4a765c12b62d40)
|
||||
|
||||
#### [v0.45.11](https://github.com/RhetTbull/osxphotos/compare/v0.45.10...v0.45.11)
|
||||
|
||||
> 13 February 2022
|
||||
|
||||
- beta fix for #633, fix face regions in exiftool [`afbda03`](https://github.com/RhetTbull/osxphotos/commit/afbda030bce87f914445ebbced3f0e110e2e203b)
|
||||
- Updated docs [skip ci] [`65d51ab`](https://github.com/RhetTbull/osxphotos/commit/65d51ab1290e7c7804021e24829b93f5dce81245)
|
||||
|
||||
#### [v0.45.10](https://github.com/RhetTbull/osxphotos/compare/v0.45.9...v0.45.10)
|
||||
|
||||
> 12 February 2022
|
||||
|
||||
- Added --force-update, #621 [`30abddd`](https://github.com/RhetTbull/osxphotos/commit/30abdddaf3765f1d604984d4781b78b7806871e1)
|
||||
|
||||
#### [v0.45.9](https://github.com/RhetTbull/osxphotos/compare/v0.45.8...v0.45.9)
|
||||
|
||||
> 12 February 2022
|
||||
|
||||
- Added --force-update, #621 [`bfa888a`](https://github.com/RhetTbull/osxphotos/commit/bfa888adc5658a2845dcaa9b7ea360926ed4f000)
|
||||
- Refactored fix for #627 [`5fb686a`](https://github.com/RhetTbull/osxphotos/commit/5fb686ac0c231932c2695fc550a0824307bd3c5f)
|
||||
- Fix for #630 [`ac4083b`](https://github.com/RhetTbull/osxphotos/commit/ac4083bfbbabc8550718f0f7f8aadc635c05eb25)
|
||||
|
||||
#### [v0.45.8](https://github.com/RhetTbull/osxphotos/compare/v0.45.6...v0.45.8)
|
||||
|
||||
> 5 February 2022
|
||||
|
||||
33
README.md
33
README.md
@@ -783,8 +783,15 @@ Options:
|
||||
folder.
|
||||
--deleted-only Include only photos from the 'Recently
|
||||
Deleted' folder.
|
||||
--update Only export new or updated files. See notes
|
||||
below on export and --update.
|
||||
--update Only export new or updated files. See also
|
||||
--force-update and notes below on export and
|
||||
--update.
|
||||
--force-update Only export new or updated files. Unlike
|
||||
--update, --force-update will re-export photos
|
||||
if their metadata has changed even if this
|
||||
would not otherwise trigger an export. See
|
||||
also --update and notes below on export and
|
||||
--update.
|
||||
--ignore-signature When used with '--update', ignores file
|
||||
signature when updating files. This is useful
|
||||
if you have processed or edited exported
|
||||
@@ -1166,6 +1173,11 @@ Options:
|
||||
'.osxphotos_export.db' in the export
|
||||
directory. If --exportdb is specified, it
|
||||
will be saved to the specified file.
|
||||
--ramdb Copy export database to memory during export;
|
||||
may improve performance when exporting over a
|
||||
network or slow disk but could result in
|
||||
losing update state information if the program
|
||||
is interrupted or crashes.
|
||||
--load-config <config file path>
|
||||
Load options from file as written with --save-
|
||||
config. This allows you to save a complex
|
||||
@@ -1179,10 +1191,11 @@ Options:
|
||||
corresponding values in the config file.
|
||||
--save-config <config file path>
|
||||
Save options to file for use with --load-
|
||||
config. File format is TOML.
|
||||
-M, --multiprocess NUMBER_OF_PROCESSES
|
||||
Run export in parallel using
|
||||
NUMBER_OF_PROCESSES processes. [x>=1]
|
||||
config. File format is TOML. See also
|
||||
--config-only.
|
||||
--config-only If specified, saves the config file but does
|
||||
not export any files; must be used with
|
||||
--save-config.
|
||||
--help Show this message and exit.
|
||||
|
||||
** Export **
|
||||
@@ -1728,7 +1741,7 @@ Substitution Description
|
||||
{lf} A line feed: '\n', alias for {newline}
|
||||
{cr} A carriage return: '\r'
|
||||
{crlf} a carriage return + line feed: '\r\n'
|
||||
{osxphotos_version} The osxphotos version, e.g. '0.45.8'
|
||||
{osxphotos_version} The osxphotos version, e.g. '0.46.1'
|
||||
{osxphotos_cmd_line} The full command line used to run osxphotos
|
||||
|
||||
The following substitutions may result in multiple values. Thus if specified for
|
||||
@@ -3632,7 +3645,7 @@ The following template field substitutions are availabe for use the templating s
|
||||
|{lf}|A line feed: '\n', alias for {newline}|
|
||||
|{cr}|A carriage return: '\r'|
|
||||
|{crlf}|a carriage return + line feed: '\r\n'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.45.8'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.46.1'|
|
||||
|{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|
|
||||
@@ -3732,7 +3745,7 @@ Args:
|
||||
|
||||
Returns: ExportResults instance
|
||||
|
||||
*Note*: to use dry run mode, you must set options.dry_run=True and also pass in memory version of export_db, and no-op fileutil (e.g. ExportDBInMemory and FileUtilNoOp) in options.export_db and options.fileutil respectively.
|
||||
*Note*: to use dry run mode, you must set options.dry_run=True and also pass in memory version of export_db, and no-op fileutil (e.g. `ExportDBInMemory` and `FileUtilNoOp`) in options.export_db and options.fileutil respectively.
|
||||
|
||||
#### `ExportOptions`
|
||||
|
||||
@@ -3748,7 +3761,7 @@ Attributes:
|
||||
- exiftool_flags (list of str): optional list of flags to pass to exiftool when using exiftool option, e.g ["-m", "-F"]
|
||||
- exiftool: (bool, default = False): if True, will use exiftool to write metadata to export file
|
||||
- export_as_hardlink: (bool, default=False): if True, will hardlink files instead of copying them
|
||||
- export_db: (ExportDB_ABC): instance of a class that conforms to ExportDB_ABC with methods for getting/setting data related to exported files to compare update state
|
||||
- export_db: (ExportDB): instance of a class that conforms to ExportDB with methods for getting/setting data related to exported files to compare update state
|
||||
- fileutil: (FileUtilABC): class that conforms to FileUtilABC with various file utilities
|
||||
- ignore_date_modified (bool): for use with sidecar and exiftool; if True, sets EXIF:ModifyDate to EXIF:DateTimeOriginal even if date_modified is set
|
||||
- ignore_signature (bool, default=False): ignore file signature when used with update (look only at filename)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
build
|
||||
m2r2
|
||||
pdbpp
|
||||
pyinstaller==4.4
|
||||
pytest-mock
|
||||
pytest==6.2.4
|
||||
Sphinx
|
||||
sphinx_click
|
||||
sphinx_rtd_theme
|
||||
sphinxcontrib-programoutput
|
||||
twine
|
||||
wheel
|
||||
Sphinx
|
||||
wheel
|
||||
@@ -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: bf43bf49b725c31ce72a8823e4f8012b
|
||||
config: d6da9902a4771e5081ae73c361960af8
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Overview: module code — osxphotos 0.43.9 documentation</title>
|
||||
<title>Overview: module code — osxphotos 0.46.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
@@ -31,11 +31,7 @@
|
||||
<div class="body" role="main">
|
||||
|
||||
<h1>All modules for which code is available</h1>
|
||||
<ul><li><a href="osxphotos/photoinfo/_photoinfo_exifinfo.html">osxphotos.photoinfo._photoinfo_exifinfo</a></li>
|
||||
<li><a href="osxphotos/photoinfo/_photoinfo_export.html">osxphotos.photoinfo._photoinfo_export</a></li>
|
||||
<li><a href="osxphotos/photoinfo/_photoinfo_scoreinfo.html">osxphotos.photoinfo._photoinfo_scoreinfo</a></li>
|
||||
<li><a href="osxphotos/photoinfo/_photoinfo_searchinfo.html">osxphotos.photoinfo._photoinfo_searchinfo</a></li>
|
||||
<li><a href="osxphotos/photoinfo/photoinfo.html">osxphotos.photoinfo.photoinfo</a></li>
|
||||
<ul><li><a href="osxphotos/photoinfo.html">osxphotos.photoinfo</a></li>
|
||||
<li><a href="osxphotos/photosdb/photosdb.html">osxphotos.photosdb.photosdb</a></li>
|
||||
</ul>
|
||||
|
||||
@@ -93,7 +89,7 @@
|
||||
©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>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
</div>
|
||||
|
||||
1868
docs/_modules/osxphotos/photoinfo.html
Normal file
1868
docs/_modules/osxphotos/photoinfo.html
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>osxphotos.photosdb.photosdb — osxphotos 0.43.8 documentation</title>
|
||||
<title>osxphotos.photosdb.photosdb — osxphotos 0.46.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/alabaster.css" />
|
||||
<script data-url_root="../../../" id="documentation_options" src="../../../_static/documentation_options.js"></script>
|
||||
@@ -60,22 +60,28 @@
|
||||
<span class="n">_PHOTO_TYPE</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_3_VERSION</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_4_ALBUM_KIND</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_4_ALBUM_TYPE_ALBUM</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_4_ALBUM_TYPE_PROJECT</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_4_ALBUM_TYPE_SLIDESHOW</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_4_ROOT_FOLDER</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_4_TOP_LEVEL_ALBUM</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_4_TOP_LEVEL_ALBUMS</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_4_VERSION</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_5_ALBUM_KIND</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_5_FOLDER_KIND</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_5_IMPORT_SESSION_ALBUM_KIND</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_5_PROJECT_ALBUM_KIND</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_5_ROOT_FOLDER_KIND</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_5_SHARED_ALBUM_KIND</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_5_VERSION</span><span class="p">,</span>
|
||||
<span class="n">_TESTED_OS_VERSIONS</span><span class="p">,</span>
|
||||
<span class="n">_UNKNOWN_PERSON</span><span class="p">,</span>
|
||||
<span class="n">BURST_KEY</span><span class="p">,</span>
|
||||
<span class="n">BURST_PICK_TYPE_NONE</span><span class="p">,</span>
|
||||
<span class="n">BURST_SELECTED</span><span class="p">,</span>
|
||||
<span class="n">TIME_DELTA</span><span class="p">,</span>
|
||||
<span class="p">)</span>
|
||||
<span class="kn">from</span> <span class="nn">.._version</span> <span class="kn">import</span> <span class="n">__version__</span>
|
||||
<span class="kn">from</span> <span class="nn">..albuminfo</span> <span class="kn">import</span> <span class="n">AlbumInfo</span><span class="p">,</span> <span class="n">FolderInfo</span><span class="p">,</span> <span class="n">ImportInfo</span>
|
||||
<span class="kn">from</span> <span class="nn">..albuminfo</span> <span class="kn">import</span> <span class="n">AlbumInfo</span><span class="p">,</span> <span class="n">FolderInfo</span><span class="p">,</span> <span class="n">ImportInfo</span><span class="p">,</span> <span class="n">ProjectInfo</span>
|
||||
<span class="kn">from</span> <span class="nn">..datetime_utils</span> <span class="kn">import</span> <span class="n">datetime_has_tz</span><span class="p">,</span> <span class="n">datetime_naive_to_local</span>
|
||||
<span class="kn">from</span> <span class="nn">..fileutil</span> <span class="kn">import</span> <span class="n">FileUtil</span>
|
||||
<span class="kn">from</span> <span class="nn">..personinfo</span> <span class="kn">import</span> <span class="n">PersonInfo</span>
|
||||
@@ -94,6 +100,8 @@
|
||||
<span class="p">)</span>
|
||||
<span class="kn">from</span> <span class="nn">.photosdb_utils</span> <span class="kn">import</span> <span class="n">get_db_model_version</span><span class="p">,</span> <span class="n">get_db_version</span>
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"PhotosDB"</span><span class="p">]</span>
|
||||
|
||||
<span class="c1"># TODO: Add test for imageTimeZoneOffsetSeconds = None</span>
|
||||
<span class="c1"># TODO: Add test for __str__</span>
|
||||
<span class="c1"># TODO: Add special albums and magic albums</span>
|
||||
@@ -462,7 +470,7 @@
|
||||
<span class="k">for</span> <span class="n">folder</span><span class="p">,</span> <span class="n">detail</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbfolder_details</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">detail</span><span class="p">[</span><span class="s2">"intrash"</span><span class="p">]</span>
|
||||
<span class="ow">and</span> <span class="ow">not</span> <span class="n">detail</span><span class="p">[</span><span class="s2">"isMagic"</span><span class="p">]</span>
|
||||
<span class="ow">and</span> <span class="n">detail</span><span class="p">[</span><span class="s2">"parentFolderUuid"</span><span class="p">]</span> <span class="o">==</span> <span class="n">_PHOTOS_4_TOP_LEVEL_ALBUM</span>
|
||||
<span class="ow">and</span> <span class="n">detail</span><span class="p">[</span><span class="s2">"parentFolderUuid"</span><span class="p">]</span> <span class="ow">in</span> <span class="n">_PHOTOS_4_TOP_LEVEL_ALBUMS</span>
|
||||
<span class="p">]</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">folders</span> <span class="o">=</span> <span class="p">[</span>
|
||||
@@ -483,7 +491,7 @@
|
||||
<span class="k">for</span> <span class="n">folder</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbfolder_details</span><span class="o">.</span><span class="n">values</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">folder</span><span class="p">[</span><span class="s2">"intrash"</span><span class="p">]</span>
|
||||
<span class="ow">and</span> <span class="ow">not</span> <span class="n">folder</span><span class="p">[</span><span class="s2">"isMagic"</span><span class="p">]</span>
|
||||
<span class="ow">and</span> <span class="n">folder</span><span class="p">[</span><span class="s2">"parentFolderUuid"</span><span class="p">]</span> <span class="o">==</span> <span class="n">_PHOTOS_4_TOP_LEVEL_ALBUM</span>
|
||||
<span class="ow">and</span> <span class="n">folder</span><span class="p">[</span><span class="s2">"parentFolderUuid"</span><span class="p">]</span> <span class="ow">in</span> <span class="n">_PHOTOS_4_TOP_LEVEL_ALBUMS</span>
|
||||
<span class="p">]</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">folder_names</span> <span class="o">=</span> <span class="p">[</span>
|
||||
@@ -562,6 +570,18 @@
|
||||
<span class="p">]</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_import_info</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">project_info</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""return list of AlbumInfo projects for each project in the database"""</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">_project_info</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">_project_info</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="n">ProjectInfo</span><span class="p">(</span><span class="n">db</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span> <span class="n">uuid</span><span class="o">=</span><span class="n">album</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">album</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_album_uuids</span><span class="p">(</span><span class="n">project</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||
<span class="p">]</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_project_info</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">db_version</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""return the database version as stored in LiGlobals table"""</span>
|
||||
@@ -673,14 +693,18 @@
|
||||
|
||||
<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>
|
||||
<span class="n">fullname</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">if</span> <span class="n">person</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">_UNKNOWN_PERSON</span>
|
||||
<span class="n">fullname</span> <span class="o">=</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">2</span><span class="p">])</span>
|
||||
<span class="k">if</span> <span class="n">person</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
||||
<span class="k">else</span> <span class="n">_UNKNOWN_PERSON</span>
|
||||
<span class="p">)</span>
|
||||
<span class="bp">self</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="o">=</span> <span class="p">{</span>
|
||||
<span class="s2">"pk"</span><span class="p">:</span> <span class="n">pk</span><span class="p">,</span>
|
||||
<span class="s2">"uuid"</span><span class="p">:</span> <span class="n">person</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span>
|
||||
<span class="s2">"fullname"</span><span class="p">:</span> <span class="n">fullname</span><span class="p">,</span>
|
||||
<span class="s2">"facecount"</span><span class="p">:</span> <span class="n">person</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span>
|
||||
<span class="s2">"keyface"</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">"displayname"</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">"displayname"</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">"photo_uuid"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"keyface_uuid"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="p">}</span>
|
||||
@@ -747,13 +771,6 @@
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbfaces_pk</span><span class="p">[</span><span class="n">pk</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">uuid</span><span class="p">]</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Finished walking through persons"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_pk</span><span class="p">))</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</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">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfaces_pk</span><span class="p">))</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfaces_uuid</span><span class="p">))</span>
|
||||
|
||||
<span class="c1"># Get info on albums</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Processing albums."</span><span class="p">)</span>
|
||||
<span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
|
||||
@@ -881,24 +898,15 @@
|
||||
<span class="c1"># build folder hierarchy</span>
|
||||
<span class="k">for</span> <span class="n">album</span><span class="p">,</span> <span class="n">details</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_details</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
||||
<span class="n">parent_folder</span> <span class="o">=</span> <span class="n">details</span><span class="p">[</span><span class="s2">"folderUuid"</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="n">details</span><span class="p">[</span>
|
||||
<span class="s2">"albumSubclass"</span>
|
||||
<span class="p">]</span> <span class="o">==</span> <span class="n">_PHOTOS_4_ALBUM_KIND</span> <span class="ow">and</span> <span class="n">parent_folder</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span>
|
||||
<span class="n">_PHOTOS_4_TOP_LEVEL_ALBUM</span>
|
||||
<span class="p">]:</span>
|
||||
<span class="k">if</span> <span class="p">(</span>
|
||||
<span class="n">details</span><span class="p">[</span><span class="s2">"albumSubclass"</span><span class="p">]</span> <span class="o">==</span> <span class="n">_PHOTOS_4_ALBUM_KIND</span>
|
||||
<span class="ow">and</span> <span class="n">parent_folder</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">_PHOTOS_4_TOP_LEVEL_ALBUMS</span>
|
||||
<span class="p">):</span>
|
||||
<span class="n">folder_hierarchy</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_build_album_folder_hierarchy_4</span><span class="p">(</span><span class="n">parent_folder</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_folders</span><span class="p">[</span><span class="n">album</span><span class="p">]</span> <span class="o">=</span> <span class="n">folder_hierarchy</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_folders</span><span class="p">[</span><span class="n">album</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Finished walking through albums"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbums_album</span><span class="p">))</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbums_uuid</span><span class="p">))</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_details</span><span class="p">))</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_folders</span><span class="p">))</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfolder_details</span><span class="p">))</span>
|
||||
|
||||
<span class="c1"># Get info on keywords</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Processing keywords."</span><span class="p">)</span>
|
||||
<span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
|
||||
@@ -914,13 +922,16 @@
|
||||
<span class="sd"> RKMaster.uuid = RKVersion.masterUuid</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">c</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">keyword</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_uuid</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_uuid</span><span class="p">[</span><span class="n">keyword</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">keyword</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_keyword</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_keyword</span><span class="p">[</span><span class="n">keyword</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_uuid</span><span class="p">[</span><span class="n">keyword</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">keyword</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_keyword</span><span class="p">[</span><span class="n">keyword</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">keyword</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
|
||||
<span class="k">for</span> <span class="n">keyword_title</span><span class="p">,</span> <span class="n">keyword_uuid</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">c</span><span class="p">:</span>
|
||||
<span class="n">keyword_title</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">keyword_title</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">_dbkeywords_uuid</span><span class="p">[</span><span class="n">keyword_uuid</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">keyword_title</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_uuid</span><span class="p">[</span><span class="n">keyword_uuid</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">keyword_title</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">_dbkeywords_keyword</span><span class="p">[</span><span class="n">keyword_title</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">keyword_uuid</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_keyword</span><span class="p">[</span><span class="n">keyword_title</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">keyword_uuid</span><span class="p">]</span>
|
||||
|
||||
<span class="c1"># Get info on disk volumes</span>
|
||||
<span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s2">"select RKVolume.modelId, RKVolume.name from RKVolume"</span><span class="p">)</span>
|
||||
@@ -1042,13 +1053,11 @@
|
||||
|
||||
<span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">c</span><span class="p">:</span>
|
||||
<span class="n">uuid</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="n">_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"uuid = '</span><span class="si">{</span><span class="n">uuid</span><span class="si">}</span><span class="s2">, master = '</span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"_uuid"</span><span class="p">]</span> <span class="o">=</span> <span class="n">uuid</span> <span class="c1"># stored here for easier debugging</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"modelID"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"masterUuid"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"filename"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"filename"</span><span class="p">]</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">3</span><span class="p">])</span>
|
||||
|
||||
<span class="c1"># There are sometimes negative values for lastmodifieddate in the database</span>
|
||||
<span class="c1"># I don't know what these mean but they will raise exception in datetime if</span>
|
||||
@@ -1287,13 +1296,13 @@
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"volumeId"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"imagePath"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"isMissing"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"originalFilename"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"originalFilename"</span><span class="p">]</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">4</span><span class="p">])</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"UTI"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"modelID"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"fileSize"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">7</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"isTrulyRAW"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"alternateMasterUuid"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"filename"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"filename"</span><span class="p">]</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">10</span><span class="p">])</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos_master</span><span class="p">[</span><span class="n">uuid</span><span class="p">]</span> <span class="o">=</span> <span class="n">info</span>
|
||||
|
||||
<span class="c1"># get details needed to find path of the edited photos</span>
|
||||
@@ -1565,39 +1574,6 @@
|
||||
|
||||
<span class="c1"># done processing, dump debug data if requested</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Done processing details from Photos library."</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Faces (_dbfaces_uuid):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfaces_uuid</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Persons (_dbpersons_pk):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_pk</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Keywords by uuid (_dbkeywords_uuid):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_uuid</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Keywords by keyword (_dbkeywords_keywords):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_keyword</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Albums by uuid (_dbalbums_uuid):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbums_uuid</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Albums by album (_dbalbums_albums):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbums_album</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Album details (_dbalbum_details):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_details</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Album titles (_dbalbum_titles):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_titles</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Volumes (_dbvolumes):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbvolumes</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Photos (_dbphotos):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Burst Photos (dbphotos_burst:"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos_burst</span><span class="p">))</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_build_album_folder_hierarchy_4</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="n">folders</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||||
<span class="sd">"""recursively build folder/album hierarchy</span>
|
||||
@@ -1615,7 +1591,7 @@
|
||||
<span class="k">if</span> <span class="n">parent_uuid</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="n">folders</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">parent_uuid</span> <span class="o">==</span> <span class="n">_PHOTOS_4_TOP_LEVEL_ALBUM</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="n">parent_uuid</span> <span class="ow">in</span> <span class="n">_PHOTOS_4_TOP_LEVEL_ALBUMS</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">folders</span><span class="p">:</span>
|
||||
<span class="c1"># this is a top-level folder with no sub-folders</span>
|
||||
<span class="n">folders</span> <span class="o">=</span> <span class="p">{</span><span class="n">uuid</span><span class="p">:</span> <span class="kc">None</span><span class="p">}</span>
|
||||
@@ -1688,7 +1664,7 @@
|
||||
<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>
|
||||
<span class="n">fullname</span> <span class="o">=</span> <span class="p">(</span>
|
||||
<span class="n">person</span><span class="p">[</span><span class="mi">2</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">2</span><span class="p">])</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="n">person</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">""</span> <span class="ow">and</span> <span class="n">person</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">)</span>
|
||||
<span class="k">else</span> <span class="n">_UNKNOWN_PERSON</span>
|
||||
<span class="p">)</span>
|
||||
@@ -1698,7 +1674,7 @@
|
||||
<span class="s2">"fullname"</span><span class="p">:</span> <span class="n">fullname</span><span class="p">,</span>
|
||||
<span class="s2">"facecount"</span><span class="p">:</span> <span class="n">person</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span>
|
||||
<span class="s2">"keyface"</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">"displayname"</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">"displayname"</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">"photo_uuid"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"keyface_uuid"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="p">}</span>
|
||||
@@ -1762,13 +1738,6 @@
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbfaces_pk</span><span class="p">[</span><span class="n">pk</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">uuid</span><span class="p">]</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Finished walking through persons"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_pk</span><span class="p">))</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</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">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfaces_pk</span><span class="p">))</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfaces_uuid</span><span class="p">))</span>
|
||||
|
||||
<span class="c1"># get details about albums</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Processing albums."</span><span class="p">)</span>
|
||||
<span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
|
||||
@@ -1885,13 +1854,6 @@
|
||||
<span class="c1"># shared albums can't be in folders</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_folders</span><span class="p">[</span><span class="n">album</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Finished walking through albums"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbums_album</span><span class="p">))</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbums_uuid</span><span class="p">))</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_details</span><span class="p">))</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_folders</span><span class="p">))</span>
|
||||
|
||||
<span class="c1"># get details on keywords</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Processing keywords."</span><span class="p">)</span>
|
||||
<span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
|
||||
@@ -1901,29 +1863,22 @@
|
||||
<span class="s2"> JOIN Z_1KEYWORDS ON Z_1KEYWORDS.Z_1ASSETATTRIBUTES = ZADDITIONALASSETATTRIBUTES.Z_PK </span>
|
||||
<span class="s2"> JOIN ZKEYWORD ON ZKEYWORD.Z_PK = </span><span class="si">{</span><span class="n">keyword_join</span><span class="si">}</span><span class="s2"> """</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">c</span><span class="p">:</span>
|
||||
<span class="n">keyword_title</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">keyword</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">keyword</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_uuid</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_uuid</span><span class="p">[</span><span class="n">keyword</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">keyword_title</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_keyword</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_keyword</span><span class="p">[</span><span class="n">keyword_title</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_uuid</span><span class="p">[</span><span class="n">keyword</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">keyword</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_keyword</span><span class="p">[</span><span class="n">keyword_title</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">keyword</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Finished walking through keywords"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_keyword</span><span class="p">))</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_uuid</span><span class="p">))</span>
|
||||
<span class="k">for</span> <span class="n">keyword_title</span><span class="p">,</span> <span class="n">keyword_uuid</span> <span class="ow">in</span> <span class="n">c</span><span class="p">:</span>
|
||||
<span class="n">keyword_title</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">keyword_title</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">_dbkeywords_uuid</span><span class="p">[</span><span class="n">keyword_uuid</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">keyword_title</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_uuid</span><span class="p">[</span><span class="n">keyword_uuid</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">keyword_title</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">_dbkeywords_keyword</span><span class="p">[</span><span class="n">keyword_title</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">keyword_uuid</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_keyword</span><span class="p">[</span><span class="n">keyword_title</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">keyword_uuid</span><span class="p">]</span>
|
||||
|
||||
<span class="c1"># get details on disk volumes</span>
|
||||
<span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s2">"SELECT ZUUID, ZNAME from ZFILESYSTEMVOLUME"</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">vol</span> <span class="ow">in</span> <span class="n">c</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbvolumes</span><span class="p">[</span><span class="n">vol</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span> <span class="o">=</span> <span class="n">vol</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Finished walking through volumes"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbvolumes</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># get details about photos</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Processing photo details."</span><span class="p">)</span>
|
||||
<span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
|
||||
@@ -2057,8 +2012,8 @@
|
||||
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"hidden"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"favorite"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"originalFilename"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"filename"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">12</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"originalFilename"</span><span class="p">]</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">3</span><span class="p">])</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"filename"</span><span class="p">]</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">12</span><span class="p">])</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"directory"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span>
|
||||
|
||||
<span class="c1"># set latitude and longitude</span>
|
||||
@@ -2534,50 +2489,7 @@
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Processing moments."</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_process_moments</span><span class="p">()</span>
|
||||
|
||||
<span class="c1"># done processing, dump debug data if requested</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Done processing details from Photos library."</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Faces (_dbfaces_uuid):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfaces_uuid</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Persons (_dbpersons_pk):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_pk</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Keywords by uuid (_dbkeywords_uuid):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_uuid</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Keywords by keyword (_dbkeywords_keywords):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_keyword</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Albums by uuid (_dbalbums_uuid):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbums_uuid</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Albums by album (_dbalbums_albums):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbums_album</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Album details (_dbalbum_details):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_details</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Album titles (_dbalbum_titles):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_titles</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Album folders (_dbalbum_folders):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_folders</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Album parent folders (_dbalbum_parent_folders):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_parent_folders</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Albums pk (_dbalbums_pk):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbalbums_pk</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Volumes (_dbvolumes):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbvolumes</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Photos (_dbphotos):"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">))</span>
|
||||
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Burst Photos (dbphotos_burst:"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">pformat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos_burst</span><span class="p">))</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_process_moments</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Process data from ZMOMENT table"""</span>
|
||||
@@ -2638,8 +2550,8 @@
|
||||
<span class="n">moment_info</span><span class="p">[</span><span class="s2">"modificationDate"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span>
|
||||
<span class="n">moment_info</span><span class="p">[</span><span class="s2">"representativeDate"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">7</span><span class="p">]</span>
|
||||
<span class="n">moment_info</span><span class="p">[</span><span class="s2">"startDate"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span>
|
||||
<span class="n">moment_info</span><span class="p">[</span><span class="s2">"subtitle"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span>
|
||||
<span class="n">moment_info</span><span class="p">[</span><span class="s2">"title"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span>
|
||||
<span class="n">moment_info</span><span class="p">[</span><span class="s2">"subtitle"</span><span class="p">]</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">9</span><span class="p">])</span>
|
||||
<span class="n">moment_info</span><span class="p">[</span><span class="s2">"title"</span><span class="p">]</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">10</span><span class="p">])</span>
|
||||
<span class="n">moment_info</span><span class="p">[</span><span class="s2">"uuid"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">11</span><span class="p">]</span>
|
||||
|
||||
<span class="c1"># if both lat/lon == -180, then it means location undefined</span>
|
||||
@@ -2858,7 +2770,7 @@
|
||||
<span class="n">hierarchy</span> <span class="o">=</span> <span class="n">_recurse_folder_hierarchy</span><span class="p">(</span><span class="n">folders</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">hierarchy</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_get_album_uuids</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">shared</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">import_session</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
||||
<span class="k">def</span> <span class="nf">_get_album_uuids</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">shared</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">import_session</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">project</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
||||
<span class="sd">"""Return list of album UUIDs found in photos database</span>
|
||||
|
||||
<span class="sd"> Filters out albums in the trash and any special album types</span>
|
||||
@@ -2866,20 +2778,21 @@
|
||||
<span class="sd"> Args:</span>
|
||||
<span class="sd"> shared: boolean; if True, returns shared albums, else normal albums</span>
|
||||
<span class="sd"> import_session: boolean, if True, returns import session albums, else normal or shared albums</span>
|
||||
<span class="sd"> project: boolean, if True, returns albums that are part of My Projects</span>
|
||||
<span class="sd"> Note: flags (shared, import_session) are mutually exclusive</span>
|
||||
|
||||
|
||||
<span class="sd"> Raises:</span>
|
||||
<span class="sd"> ValueError: raised if mutually exclusive flags passed</span>
|
||||
|
||||
<span class="sd"> Returns: list of album UUIDs</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">if</span> <span class="n">shared</span> <span class="ow">and</span> <span class="n">import_session</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="nb">sum</span><span class="p">(</span><span class="nb">bool</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">[</span><span class="n">shared</span><span class="p">,</span> <span class="n">import_session</span><span class="p">,</span> <span class="n">project</span><span class="p">])</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
||||
<span class="s2">"flags are mutually exclusive: pass zero or one of shared, import_session"</span>
|
||||
<span class="s2">"flags are mutually exclusive: pass zero or one of shared, import_session, projects"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db_version</span> <span class="o"><=</span> <span class="n">_PHOTOS_4_VERSION</span><span class="p">:</span>
|
||||
<span class="n">version4</span> <span class="o">=</span> <span class="kc">True</span>
|
||||
<span class="k">if</span> <span class="n">shared</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">"Shared albums not implemented for Photos library version </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_db_version</span><span class="si">}</span><span class="s2">"</span>
|
||||
@@ -2890,16 +2803,44 @@
|
||||
<span class="sa">f</span><span class="s2">"Import sessions not implemented for Photos library version </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_db_version</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">return</span> <span class="p">[]</span> <span class="c1"># not implemented for _PHOTOS_4_VERSION</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="k">elif</span> <span class="n">project</span><span class="p">:</span>
|
||||
<span class="n">album_type</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="n">_PHOTOS_4_ALBUM_TYPE_PROJECT</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_4_ALBUM_TYPE_SLIDESHOW</span><span class="p">,</span>
|
||||
<span class="p">]</span>
|
||||
<span class="n">album_kind</span> <span class="o">=</span> <span class="n">_PHOTOS_4_ALBUM_KIND</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">version4</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
<span class="k">if</span> <span class="n">shared</span><span class="p">:</span>
|
||||
<span class="n">album_kind</span> <span class="o">=</span> <span class="n">_PHOTOS_5_SHARED_ALBUM_KIND</span>
|
||||
<span class="k">elif</span> <span class="n">import_session</span><span class="p">:</span>
|
||||
<span class="n">album_kind</span> <span class="o">=</span> <span class="n">_PHOTOS_5_IMPORT_SESSION_ALBUM_KIND</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">album_kind</span> <span class="o">=</span> <span class="n">_PHOTOS_5_ALBUM_KIND</span>
|
||||
<span class="n">album_type</span> <span class="o">=</span> <span class="p">[</span><span class="n">_PHOTOS_4_ALBUM_TYPE_ALBUM</span><span class="p">]</span>
|
||||
<span class="n">album_kind</span> <span class="o">=</span> <span class="n">_PHOTOS_4_ALBUM_KIND</span>
|
||||
|
||||
<span class="n">album_list</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="c1"># look through _dbalbum_details because _dbalbums_album won't have empty albums it</span>
|
||||
<span class="k">for</span> <span class="n">album</span><span class="p">,</span> <span class="n">detail</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_details</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
||||
<span class="k">if</span> <span class="p">(</span>
|
||||
<span class="n">detail</span><span class="p">[</span><span class="s2">"kind"</span><span class="p">]</span> <span class="o">==</span> <span class="n">album_kind</span>
|
||||
<span class="ow">and</span> <span class="n">detail</span><span class="p">[</span><span class="s2">"albumType"</span><span class="p">]</span> <span class="ow">in</span> <span class="n">album_type</span>
|
||||
<span class="ow">and</span> <span class="ow">not</span> <span class="n">detail</span><span class="p">[</span><span class="s2">"intrash"</span><span class="p">]</span>
|
||||
<span class="ow">and</span> <span class="p">(</span>
|
||||
<span class="p">(</span><span class="n">shared</span> <span class="ow">and</span> <span class="n">detail</span><span class="p">[</span><span class="s2">"cloudownerhashedpersonid"</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">)</span>
|
||||
<span class="ow">or</span> <span class="p">(</span><span class="ow">not</span> <span class="n">shared</span> <span class="ow">and</span> <span class="n">detail</span><span class="p">[</span><span class="s2">"cloudownerhashedpersonid"</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">)</span>
|
||||
<span class="p">)</span>
|
||||
<span class="ow">and</span> <span class="n">detail</span><span class="p">[</span><span class="s2">"folderUuid"</span><span class="p">]</span> <span class="o">!=</span> <span class="n">_PHOTOS_4_ROOT_FOLDER</span>
|
||||
<span class="c1"># in Photos <= 4, special albums like "printAlbum" have kind _PHOTOS_4_ALBUM_KIND</span>
|
||||
<span class="c1"># but should not be listed here; they can be distinguished by looking</span>
|
||||
<span class="c1"># for folderUuid of _PHOTOS_4_ROOT_FOLDER as opposed to _PHOTOS_4_TOP_LEVEL_ALBUM</span>
|
||||
<span class="p">):</span>
|
||||
<span class="n">album_list</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">album</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">album_list</span>
|
||||
|
||||
<span class="c1"># Photos version 5+</span>
|
||||
<span class="k">if</span> <span class="n">shared</span><span class="p">:</span>
|
||||
<span class="n">album_kind</span> <span class="o">=</span> <span class="n">_PHOTOS_5_SHARED_ALBUM_KIND</span>
|
||||
<span class="k">elif</span> <span class="n">import_session</span><span class="p">:</span>
|
||||
<span class="n">album_kind</span> <span class="o">=</span> <span class="n">_PHOTOS_5_IMPORT_SESSION_ALBUM_KIND</span>
|
||||
<span class="k">elif</span> <span class="n">project</span><span class="p">:</span>
|
||||
<span class="n">album_kind</span> <span class="o">=</span> <span class="n">_PHOTOS_5_PROJECT_ALBUM_KIND</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">album_kind</span> <span class="o">=</span> <span class="n">_PHOTOS_5_ALBUM_KIND</span>
|
||||
|
||||
<span class="n">album_list</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="c1"># look through _dbalbum_details because _dbalbums_album won't have empty albums it</span>
|
||||
@@ -2911,13 +2852,6 @@
|
||||
<span class="p">(</span><span class="n">shared</span> <span class="ow">and</span> <span class="n">detail</span><span class="p">[</span><span class="s2">"cloudownerhashedpersonid"</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">)</span>
|
||||
<span class="ow">or</span> <span class="p">(</span><span class="ow">not</span> <span class="n">shared</span> <span class="ow">and</span> <span class="n">detail</span><span class="p">[</span><span class="s2">"cloudownerhashedpersonid"</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">)</span>
|
||||
<span class="p">)</span>
|
||||
<span class="ow">and</span> <span class="p">(</span>
|
||||
<span class="ow">not</span> <span class="n">version4</span>
|
||||
<span class="c1"># in Photos 4, special albums like "printAlbum" have kind _PHOTOS_4_ALBUM_KIND</span>
|
||||
<span class="c1"># but should not be listed here; they can be distinguished by looking</span>
|
||||
<span class="c1"># for folderUuid of _PHOTOS_4_ROOT_FOLDER as opposed to _PHOTOS_4_TOP_LEVEL_ALBUM</span>
|
||||
<span class="ow">or</span> <span class="p">(</span><span class="n">version4</span> <span class="ow">and</span> <span class="n">detail</span><span class="p">[</span><span class="s2">"folderUuid"</span><span class="p">]</span> <span class="o">!=</span> <span class="n">_PHOTOS_4_ROOT_FOLDER</span><span class="p">)</span>
|
||||
<span class="p">)</span>
|
||||
<span class="p">):</span>
|
||||
<span class="n">album_list</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">album</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">album_list</span>
|
||||
@@ -3020,6 +2954,7 @@
|
||||
<span class="k">if</span> <span class="n">keywords</span><span class="p">:</span>
|
||||
<span class="n">keyword_set</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
|
||||
<span class="k">for</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">keywords</span><span class="p">:</span>
|
||||
<span class="n">keyword</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">keyword</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_keyword</span><span class="p">:</span>
|
||||
<span class="n">keyword_set</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbkeywords_keyword</span><span class="p">[</span><span class="n">keyword</span><span class="p">])</span>
|
||||
<span class="n">photos_sets</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">keyword_set</span><span class="p">)</span>
|
||||
@@ -3027,6 +2962,7 @@
|
||||
<span class="k">if</span> <span class="n">persons</span><span class="p">:</span>
|
||||
<span class="n">person_set</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
|
||||
<span class="k">for</span> <span class="n">person</span> <span class="ow">in</span> <span class="n">persons</span><span class="p">:</span>
|
||||
<span class="n">person</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">person</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">person</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_fullname</span><span class="p">:</span>
|
||||
<span class="k">for</span> <span class="n">pk</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_fullname</span><span class="p">[</span><span class="n">person</span><span class="p">]:</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
@@ -3058,6 +2994,7 @@
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="s2">"burst"</span><span class="p">]</span> <span class="ow">and</span> <span class="ow">not</span> <span class="p">(</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="s2">"burstPickType"</span><span class="p">]</span> <span class="o">&</span> <span class="n">BURST_SELECTED</span>
|
||||
<span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="s2">"burstPickType"</span><span class="p">]</span> <span class="o">&</span> <span class="n">BURST_KEY</span>
|
||||
<span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="s2">"burstPickType"</span><span class="p">]</span> <span class="o">==</span> <span class="n">BURST_PICK_TYPE_NONE</span>
|
||||
<span class="p">):</span>
|
||||
<span class="c1"># not a key/selected burst photo, don't include in returned results</span>
|
||||
<span class="k">continue</span>
|
||||
@@ -3068,8 +3005,6 @@
|
||||
<span class="p">):</span>
|
||||
<span class="n">info</span> <span class="o">=</span> <span class="n">PhotoInfo</span><span class="p">(</span><span class="n">db</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span> <span class="n">uuid</span><span class="o">=</span><span class="n">p</span><span class="p">,</span> <span class="n">info</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">p</span><span class="p">])</span>
|
||||
<span class="n">photoinfo</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">info</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">_debug</span><span class="p">:</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"photoinfo: </span><span class="si">{</span><span class="n">pformat</span><span class="p">(</span><span class="n">photoinfo</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">photoinfo</span></div>
|
||||
|
||||
@@ -3406,23 +3341,35 @@
|
||||
<span class="c1"># case-insensitive</span>
|
||||
<span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">name</span><span class="p">:</span>
|
||||
<span class="n">n</span> <span class="o">=</span> <span class="n">n</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
|
||||
<span class="n">photo_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span>
|
||||
<span class="p">[</span>
|
||||
<span class="n">p</span>
|
||||
<span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span>
|
||||
<span class="k">if</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">p</span><span class="o">.</span><span class="n">filename</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
|
||||
<span class="ow">or</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">p</span><span class="o">.</span><span class="n">original_filename</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
|
||||
<span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db_version</span> <span class="o">>=</span> <span class="n">_PHOTOS_5_VERSION</span><span class="p">:</span>
|
||||
<span class="c1"># search only original_filename (#594)</span>
|
||||
<span class="n">photo_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span>
|
||||
<span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">p</span><span class="o">.</span><span class="n">original_filename</span><span class="o">.</span><span class="n">lower</span><span class="p">()]</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">photo_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span>
|
||||
<span class="p">[</span>
|
||||
<span class="n">p</span>
|
||||
<span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span>
|
||||
<span class="k">if</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">p</span><span class="o">.</span><span class="n">filename</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
|
||||
<span class="ow">or</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">p</span><span class="o">.</span><span class="n">original_filename</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
|
||||
<span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">name</span><span class="p">:</span>
|
||||
<span class="n">photo_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span>
|
||||
<span class="p">[</span>
|
||||
<span class="n">p</span>
|
||||
<span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span>
|
||||
<span class="k">if</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">p</span><span class="o">.</span><span class="n">filename</span> <span class="ow">or</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">p</span><span class="o">.</span><span class="n">original_filename</span>
|
||||
<span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db_version</span> <span class="o">>=</span> <span class="n">_PHOTOS_5_VERSION</span><span class="p">:</span>
|
||||
<span class="c1"># search only original_filename (#594)</span>
|
||||
<span class="n">photo_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span>
|
||||
<span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">p</span><span class="o">.</span><span class="n">original_filename</span><span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">photo_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span>
|
||||
<span class="p">[</span>
|
||||
<span class="n">p</span>
|
||||
<span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span>
|
||||
<span class="k">if</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">p</span><span class="o">.</span><span class="n">filename</span> <span class="ow">or</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">p</span><span class="o">.</span><span class="n">original_filename</span>
|
||||
<span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">photos</span> <span class="o">=</span> <span class="n">photo_list</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">min_size</span><span class="p">:</span>
|
||||
@@ -3621,6 +3568,7 @@
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../cli.html">osxphotos command line interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../modules.html">osxphotos</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../reference.html">osxphotos package</a></li>
|
||||
</ul>
|
||||
|
||||
@@ -3659,7 +3607,7 @@
|
||||
©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>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -3,4 +3,6 @@ osxphotos command line interface (CLI)
|
||||
|
||||
.. click:: osxphotos.cli:cli
|
||||
:prog: osxphotos
|
||||
:nested: full
|
||||
:nested: full
|
||||
|
||||
.. program-output:: python3 -m osxphotos --help
|
||||
2
docs/_static/documentation_options.js
vendored
2
docs/_static/documentation_options.js
vendored
@@ -1,6 +1,6 @@
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||
VERSION: '0.45.8',
|
||||
VERSION: '0.46.1',
|
||||
LANGUAGE: 'None',
|
||||
COLLAPSE_INDEX: false,
|
||||
BUILDER: 'html',
|
||||
|
||||
2228
docs/cli.html
2228
docs/cli.html
File diff suppressed because it is too large
Load Diff
2714
docs/genindex.html
2714
docs/genindex.html
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<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 osxphotos’s documentation! — osxphotos 0.45.8 documentation</title>
|
||||
<title>Welcome to osxphotos’s documentation! — osxphotos 0.46.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
@@ -281,7 +281,32 @@ Alternatively, you can also run the command line utility like this: <code class=
|
||||
<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">
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="cli.html">osxphotos command line interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="cli.html">osxphotos command line interface (CLI)</a><ul>
|
||||
<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-diff">diff</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-run">run</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-snap">snap</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>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-uuid">uuid</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<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>
|
||||
</ul>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<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 — osxphotos 0.45.8 documentation</title>
|
||||
<title>osxphotos — osxphotos 0.46.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
|
||||
BIN
docs/objects.inv
BIN
docs/objects.inv
Binary file not shown.
@@ -6,7 +6,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<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 package — osxphotos 0.45.8 documentation</title>
|
||||
<title>osxphotos package — osxphotos 0.46.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
@@ -36,6 +36,883 @@
|
||||
<h1>osxphotos package<a class="headerlink" href="#osxphotos-package" title="Permalink to this headline">¶</a></h1>
|
||||
<section id="osxphotos-module">
|
||||
<h2>osxphotos module<a class="headerlink" href="#osxphotos-module" title="Permalink to this headline">¶</a></h2>
|
||||
<dl class="py class">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB">
|
||||
<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">PhotosDB</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">dbfile</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">verbose</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">exiftool</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/photosdb/photosdb.html#PhotosDB"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotosDB" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Processes a Photos.app library database to extract information about photos</p>
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.album_info">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">album_info</span></span><a class="headerlink" href="#osxphotos.PhotosDB.album_info" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list of AlbumInfo objects for each album in the photos database</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.album_info_shared">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">album_info_shared</span></span><a class="headerlink" href="#osxphotos.PhotosDB.album_info_shared" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list of AlbumInfo objects for each shared album in the photos database
|
||||
only valid for Photos 5; on Photos <= 4, prints warning and returns empty list</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.albums">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">albums</span></span><a class="headerlink" href="#osxphotos.PhotosDB.albums" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list of albums found in photos database</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.albums_as_dict">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">albums_as_dict</span></span><a class="headerlink" href="#osxphotos.PhotosDB.albums_as_dict" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return albums as dict of albums, count in reverse sorted order (descending)</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.albums_shared">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">albums_shared</span></span><a class="headerlink" href="#osxphotos.PhotosDB.albums_shared" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list of shared albums found in photos database
|
||||
only valid for Photos 5; on Photos <= 4, prints warning and returns empty list</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.albums_shared_as_dict">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">albums_shared_as_dict</span></span><a class="headerlink" href="#osxphotos.PhotosDB.albums_shared_as_dict" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns shared albums as dict of albums, count in reverse sorted order (descending)
|
||||
valid only on Photos 5; on Photos <= 4, prints warning and returns empty dict</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.db_path">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">db_path</span></span><a class="headerlink" href="#osxphotos.PhotosDB.db_path" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns path to the Photos library database PhotosDB was initialized with</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.db_version">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">db_version</span></span><a class="headerlink" href="#osxphotos.PhotosDB.db_version" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return the database version as stored in LiGlobals table</p>
|
||||
</dd></dl>
|
||||
|
||||
<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>
|
||||
<dd><p>Execute sql statement and return cursor</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.folder_info">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">folder_info</span></span><a class="headerlink" href="#osxphotos.PhotosDB.folder_info" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list FolderInfo objects representing top-level folders in the photos database</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.folders">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">folders</span></span><a class="headerlink" href="#osxphotos.PhotosDB.folders" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list of top-level folder names in the photos database</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.get_db_connection">
|
||||
<span class="sig-name descname"><span class="pre">get_db_connection</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="reference internal" href="_modules/osxphotos/photosdb/photosdb.html#PhotosDB.get_db_connection"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotosDB.get_db_connection" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Get connection to the working copy of the Photos database</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Returns</dt>
|
||||
<dd class="field-odd"><p>tuple of (connection, cursor) to sqlite3 database</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.get_photo">
|
||||
<span class="sig-name descname"><span class="pre">get_photo</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">uuid</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/osxphotos/photosdb/photosdb.html#PhotosDB.get_photo"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotosDB.get_photo" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns a single photo matching uuid</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Parameters</dt>
|
||||
<dd class="field-odd"><p><strong>uuid</strong> – the UUID of photo to get</p>
|
||||
</dd>
|
||||
<dt class="field-even">Returns</dt>
|
||||
<dd class="field-even"><p>PhotoInfo instance for photo with UUID matching uuid or None if no match</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.import_info">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">import_info</span></span><a class="headerlink" href="#osxphotos.PhotosDB.import_info" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list of ImportInfo objects for each import session in the database</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.keywords">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">keywords</span></span><a class="headerlink" href="#osxphotos.PhotosDB.keywords" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list of keywords found in photos database</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.keywords_as_dict">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">keywords_as_dict</span></span><a class="headerlink" href="#osxphotos.PhotosDB.keywords_as_dict" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return keywords as dict of keyword, count in reverse sorted order (descending)</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.labels">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">labels</span></span><a class="headerlink" href="#osxphotos.PhotosDB.labels" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list of all search info labels found in the library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.labels_as_dict">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">labels_as_dict</span></span><a class="headerlink" href="#osxphotos.PhotosDB.labels_as_dict" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>count in reverse sorted order (descending)</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Type</dt>
|
||||
<dd class="field-odd"><p>return labels as dict of label</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.labels_normalized">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">labels_normalized</span></span><a class="headerlink" href="#osxphotos.PhotosDB.labels_normalized" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list of all normalized search info labels found in the library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.labels_normalized_as_dict">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">labels_normalized_as_dict</span></span><a class="headerlink" href="#osxphotos.PhotosDB.labels_normalized_as_dict" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>count in reverse sorted order (descending)</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Type</dt>
|
||||
<dd class="field-odd"><p>return normalized labels as dict of label</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.library_path">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">library_path</span></span><a class="headerlink" href="#osxphotos.PhotosDB.library_path" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns path to the Photos library PhotosDB was initialized with</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.person_info">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">person_info</span></span><a class="headerlink" href="#osxphotos.PhotosDB.person_info" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list of PersonInfo objects for each person in the photos database</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.persons">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">persons</span></span><a class="headerlink" href="#osxphotos.PhotosDB.persons" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list of persons found in photos database</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.persons_as_dict">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">persons_as_dict</span></span><a class="headerlink" href="#osxphotos.PhotosDB.persons_as_dict" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return persons as dict of person, count in reverse sorted order (descending)</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.photos">
|
||||
<span class="sig-name descname"><span class="pre">photos</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">keywords</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">persons</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">albums</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">images</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">movies</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">from_date</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">to_date</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">intrash</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/osxphotos/photosdb/photosdb.html#PhotosDB.photos"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotosDB.photos" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Return a list of PhotoInfo objects
|
||||
If called with no args, returns the entire database of photos
|
||||
If called with args, returns photos matching the args (e.g. keywords, persons, etc.)
|
||||
If more than one arg, returns photos matching all the criteria (e.g. keywords AND persons)
|
||||
If more than one keyword, uuid, persons, albums is passed, they are treated as “OR” criteria
|
||||
e.g. keywords=[“wedding”,”vacation”] returns photos matching either keyword
|
||||
from_date and to_date may be either naive or timezone-aware datetime.datetime objects.
|
||||
If naive, timezone will be assumed to be local timezone.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Parameters</dt>
|
||||
<dd class="field-odd"><ul class="simple">
|
||||
<li><p><strong>keywords</strong> – list of keywords to search for</p></li>
|
||||
<li><p><strong>uuid</strong> – list of UUIDs to search for</p></li>
|
||||
<li><p><strong>persons</strong> – list of persons to search for</p></li>
|
||||
<li><p><strong>albums</strong> – list of album names to search for</p></li>
|
||||
<li><p><strong>images</strong> – if True, returns image files, if False, does not return images; default is True</p></li>
|
||||
<li><p><strong>movies</strong> – if True, returns movie files, if False, does not return movies; default is True</p></li>
|
||||
<li><p><strong>from_date</strong> – return photos with creation date >= from_date (datetime.datetime object, default None)</p></li>
|
||||
<li><p><strong>to_date</strong> – return photos with creation date <= to_date (datetime.datetime object, default None)</p></li>
|
||||
<li><p><strong>intrash</strong> – if True, returns only images in “Recently deleted items” folder,
|
||||
if False returns only photos that aren’t deleted; default is False</p></li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt class="field-even">Returns</dt>
|
||||
<dd class="field-even"><p>list of PhotoInfo objects</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.photos_by_uuid">
|
||||
<span class="sig-name descname"><span class="pre">photos_by_uuid</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">uuids</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/osxphotos/photosdb/photosdb.html#PhotosDB.photos_by_uuid"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotosDB.photos_by_uuid" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><dl class="simple">
|
||||
<dt>Returns a list of photos with UUID in uuids.</dt><dd><p>Does not generate error if invalid or missing UUID passed.
|
||||
This is faster than using PhotosDB.photos if you have list of UUIDs.
|
||||
Returns photos regardless of intrash state.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Parameters</dt>
|
||||
<dd class="field-odd"><p><strong>uuid</strong> – list of UUIDs of photos to get</p>
|
||||
</dd>
|
||||
<dt class="field-even">Returns</dt>
|
||||
<dd class="field-even"><p>list of PhotoInfo instance for photo with UUID matching uuid or [] if no match</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.project_info">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">project_info</span></span><a class="headerlink" href="#osxphotos.PhotosDB.project_info" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list of AlbumInfo projects for each project in the database</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotosDB.query">
|
||||
<span class="sig-name descname"><span class="pre">query</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">options</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">osxphotos.queryoptions.QueryOptions</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">→</span> <span class="sig-return-typehint"><span class="pre">List</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="#osxphotos.PhotoInfo" title="osxphotos.photoinfo.PhotoInfo"><span class="pre">osxphotos.photoinfo.PhotoInfo</span></a><span class="p"><span class="pre">]</span></span></span></span><a class="reference internal" href="_modules/osxphotos/photosdb/photosdb.html#PhotosDB.query"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotosDB.query" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Run a query against PhotosDB to extract the photos based on user supplied options</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Parameters</dt>
|
||||
<dd class="field-odd"><p><strong>options</strong> – a QueryOptions instance</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
||||
<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>
|
||||
<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">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.adjustments">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">adjustments</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.adjustments" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns AdjustmentsInfo class for adjustment data or None if no adjustments; Photos 5+ only</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.album_info">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">album_info</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.album_info" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>list of AlbumInfo objects representing albums the photo is contained in</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.albums">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">albums</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.albums" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>list of albums picture is contained in</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.asdict">
|
||||
<span class="sig-name descname"><span class="pre">asdict</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="reference internal" href="_modules/osxphotos/photoinfo.html#PhotoInfo.asdict"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotoInfo.asdict" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return dict representation</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.burst">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">burst</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.burst" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is part of a Burst photo set, otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.burst_album_info">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">burst_album_info</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.burst_album_info" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>If photo is a burst photo, returns list of AlbumInfo objects representing albums the photo is contained in as well as albums the burst key photo is contained in, otherwise returns self.album_info.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.burst_albums">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">burst_albums</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.burst_albums" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>If photo is burst photo, list of albums it is contained in as well as any albums the key photo is contained in, otherwise returns self.albums</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.burst_default_pick">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">burst_default_pick</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.burst_default_pick" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is a burst image and is the photo that Photos selected as the default image for the burst set, otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.burst_key">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">burst_key</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.burst_key" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is a burst photo and is the key image for the burst set (the image that Photos shows on top of the burst stack), otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.burst_photos">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">burst_photos</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.burst_photos" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>If photo is a burst photo, returns list of PhotoInfo objects
|
||||
that are part of the same burst photo set; otherwise returns empty list.
|
||||
self is not included in the returned list</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.burst_selected">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">burst_selected</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.burst_selected" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is a burst photo and has been selected from the burst set by the user, otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.comments">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">comments</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.comments" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns list of Comment objects for any comments on the photo (sorted by date)</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.date">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">date</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.date" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>image creation date as timezone aware datetime object</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.date_added">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">date_added</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.date_added" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Date photo was added to the database</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.date_modified">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">date_modified</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.date_modified" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>image modification date as timezone aware datetime object
|
||||
or None if no modification date set</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.date_trashed">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">date_trashed</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.date_trashed" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Date asset was placed in the trash or None</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.description">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">description</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.description" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>long / extended description of picture</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.detected_text">
|
||||
<span class="sig-name descname"><span class="pre">detected_text</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">confidence_threshold</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0.75</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/osxphotos/photoinfo.html#PhotoInfo.detected_text"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotoInfo.detected_text" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Detects text in photo and returns lists of results as (detected text, confidence)</p>
|
||||
<p>confidence_threshold: float between 0.0 and 1.0. If text detection confidence is below this threshold,
|
||||
text will not be returned. Default is TEXT_DETECTION_CONFIDENCE_THRESHOLD</p>
|
||||
<p>If photo is edited, uses the edited photo, otherwise the original; falls back to the preview image if neither edited or original is available</p>
|
||||
<p>Returns: list of (detected text, confidence) tuples</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.duplicates">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">duplicates</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.duplicates" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return list of PhotoInfo objects for possible duplicates (matching signature of original size, date, height, width) or empty list if no matching duplicates</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.exif_info">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">exif_info</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.exif_info" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns an ExifInfo object with the EXIF data for photo
|
||||
Note: the returned EXIF data is the data Photos stores in the database on import;
|
||||
ExifInfo does not provide access to the EXIF info in the actual image file
|
||||
Some or all of the fields may be None
|
||||
Only valid for Photos 5; on earlier database returns None</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.exiftool">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">exiftool</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.exiftool" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns a ExifToolCaching (read-only instance of ExifTool) object for the photo.
|
||||
Requires that exiftool (<a class="reference external" href="https://exiftool.org/">https://exiftool.org/</a>) be installed
|
||||
If exiftool not installed, logs warning and returns None
|
||||
If photo path is missing, returns None</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.export">
|
||||
<span class="sig-name descname"><span class="pre">export</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">dest</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">filename</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">edited</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">live_photo</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">raw_photo</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">export_as_hardlink</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">overwrite</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">increment</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">sidecar_json</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">sidecar_exiftool</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">sidecar_xmp</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">use_photos_export</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">120</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">exiftool</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">use_albums_as_keywords</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">use_persons_as_keywords</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">keyword_template</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">description_template</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">render_options</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">osxphotos.phototemplate.RenderOptions</span><span class="p"><span class="pre">]</span></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><a class="reference internal" href="_modules/osxphotos/photoinfo.html#PhotoInfo.export"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotoInfo.export" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>export photo
|
||||
dest: must be valid destination path (or exception raised)
|
||||
filename: (optional): name of exported picture; if not provided, will use current filename</p>
|
||||
<blockquote>
|
||||
<div><p><strong>NOTE</strong>: if provided, user must ensure file extension (suffix) is correct.
|
||||
For example, if photo is .CR2 file, edited image may be .jpeg.
|
||||
If you provide an extension different than what the actual file is,
|
||||
export will print a warning but will export the photo using the
|
||||
incorrect file extension (unless use_photos_export is true, in which case export will
|
||||
use the extension provided by Photos upon export; in this case, an incorrect extension is
|
||||
silently ignored).
|
||||
e.g. to get the extension of the edited photo,
|
||||
reference PhotoInfo.path_edited</p>
|
||||
</div></blockquote>
|
||||
<dl class="simple">
|
||||
<dt>edited: (boolean, default=False); if True will export the edited version of the photo, otherwise exports the original version</dt><dd><p>(or raise exception if no edited version)</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<p>live_photo: (boolean, default=False); if True, will also export the associated .mov for live photos
|
||||
raw_photo: (boolean, default=False); if True, will also export the associated RAW photo
|
||||
export_as_hardlink: (boolean, default=False); if True, will hardlink files instead of copying them
|
||||
overwrite: (boolean, default=False); if True will overwrite files if they already exist
|
||||
increment: (boolean, default=True); if True, will increment file name until a non-existant name is found</p>
|
||||
<blockquote>
|
||||
<div><p>if overwrite=False and increment=False, export will fail if destination file already exists</p>
|
||||
</div></blockquote>
|
||||
<dl class="simple">
|
||||
<dt>sidecar_json: if set will write a json sidecar with data in format readable by exiftool</dt><dd><p>sidecar filename will be dest/filename.json; includes exiftool tag group names (e.g. <cite>exiftool -G -j</cite>)</p>
|
||||
</dd>
|
||||
<dt>sidecar_exiftool: if set will write a json sidecar with data in format readable by exiftool</dt><dd><p>sidecar filename will be dest/filename.json; does not include exiftool tag group names (e.g. <cite>exiftool -j</cite>)</p>
|
||||
</dd>
|
||||
<dt>sidecar_xmp: if set will write an XMP sidecar with IPTC data</dt><dd><p>sidecar filename will be dest/filename.xmp</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<p>use_photos_export: (boolean, default=False); if True will attempt to export photo via applescript interaction with Photos
|
||||
timeout: (int, default=120) timeout in seconds used with use_photos_export
|
||||
exiftool: (boolean, default = False); if True, will use exiftool to write metadata to export file
|
||||
returns list of full paths to the exported files
|
||||
use_albums_as_keywords: (boolean, default = False); if True, will include album names in keywords
|
||||
when exporting metadata with exiftool or sidecar
|
||||
use_persons_as_keywords: (boolean, default = False); if True, will include person names in keywords
|
||||
when exporting metadata with exiftool or sidecar
|
||||
keyword_template: (list of strings); list of template strings that will be rendered as used as keywords
|
||||
description_template: string; optional template string that will be rendered for use as photo description
|
||||
render_options: an optional osxphotos.phototemplate.RenderOptions instance with options to pass to template renderer</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Returns</dt>
|
||||
<dd class="field-odd"><p>list of photos exported</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.external_edit">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">external_edit</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.external_edit" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if picture was edited outside of Photos using external editor</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.face_info">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">face_info</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.face_info" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>list of FaceInfo objects for faces in picture</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.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.PhotoInfo.favorite" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>True if picture is marked as favorite</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.filename">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">filename</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.filename" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>filename of the picture</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.has_raw">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">has_raw</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.has_raw" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns True if photo has an associated raw image (that is, it’s a RAW+JPEG pair), otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.hasadjustments">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">hasadjustments</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.hasadjustments" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>True if picture has adjustments / edits</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.hdr">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">hdr</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.hdr" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is an HDR photo, otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.height">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">height</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.height" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns height of the current photo version in pixels</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.hidden">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">hidden</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.hidden" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>True if picture is hidden</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.import_info">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">import_info</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.import_info" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>ImportInfo object representing import session for the photo or None if no import session</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.incloud">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">incloud</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.incloud" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is cloud asset and is synched to cloud
|
||||
False if photo is cloud asset and not yet synched to cloud
|
||||
None if photo is not cloud asset</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.intrash">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">intrash</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.intrash" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>True if picture is in trash (‘Recently Deleted’ folder)</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.iscloudasset">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">iscloudasset</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.iscloudasset" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is a cloud asset (in an iCloud library),
|
||||
otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.ismissing">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">ismissing</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.ismissing" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns true if photo is missing from disk (which means it’s not been downloaded from iCloud)</p>
|
||||
<dl class="simple">
|
||||
<dt>NOTE: the photos.db database uses an asynchrounous write-ahead log so changes in Photos</dt><dd><p>do not immediately get written to disk. In particular, I’ve noticed that downloading
|
||||
an image from the cloud does not force the database to be updated until something else
|
||||
e.g. an edit, keyword, etc. occurs forcing a database synch
|
||||
The exact process / timing is a mystery to be but be aware that if some photos were recently
|
||||
downloaded from cloud to local storate their status in the database might still show
|
||||
isMissing = 1</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.ismovie">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">ismovie</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.ismovie" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if file is a movie, otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.isphoto">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">isphoto</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.isphoto" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if file is an image, otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.israw">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">israw</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.israw" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns True if photo is a raw image. For images with an associated RAW+JPEG pair, see has_raw</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.isreference">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">isreference</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.isreference" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is a reference (not copied to the Photos library), otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.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/photoinfo.html#PhotoInfo.json"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotoInfo.json" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Return JSON representation</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.keywords">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">keywords</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.keywords" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>list of keywords for picture</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.labels">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">labels</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.labels" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns list of labels applied to photo by Photos image categorization
|
||||
only valid on Photos 5, on older libraries returns empty list</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.labels_normalized">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">labels_normalized</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.labels_normalized" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns normalized list of labels applied to photo by Photos image categorization
|
||||
only valid on Photos 5, on older libraries returns empty list</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.likes">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">likes</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.likes" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns list of Like objects for any likes on the photo (sorted by date)</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.live_photo">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">live_photo</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.live_photo" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is a live photo, otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.location">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">location</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.location" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns (latitude, longitude) as float in degrees or None</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.moment">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">moment</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.moment" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Moment photo belongs to</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.orientation">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">orientation</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.orientation" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns EXIF orientation of the current photo version as int or 0 if current orientation cannot be determined</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.original_filename">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">original_filename</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.original_filename" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>original filename of the picture
|
||||
Photos 5 mangles filenames upon import</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.original_filesize">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">original_filesize</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.original_filesize" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns filesize of original photo in bytes as int</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.original_height">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">original_height</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.original_height" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns height of the original photo version in pixels</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.original_orientation">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">original_orientation</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.original_orientation" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns EXIF orientation of the original photo version as int</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.original_width">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">original_width</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.original_width" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns width of the original photo version in pixels</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.owner">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">owner</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.owner" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Return name of photo owner for shared photos (Photos 5+ only), or None if not shared</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.panorama">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">panorama</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.panorama" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is a panorama, otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.path">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">path</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.path" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>absolute path on disk of the original picture</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.path_derivatives">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">path_derivatives</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.path_derivatives" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Return any derivative (preview) images associated with the photo as a list of paths, sorted by file size (largest first)</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.path_edited">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">path_edited</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.path_edited" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>absolute path on disk of the edited picture</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.path_edited_live_photo">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">path_edited_live_photo</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.path_edited_live_photo" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>return path to edited version of live photo movie; only valid for Photos 5+</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.path_live_photo">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">path_live_photo</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.path_live_photo" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns path to the associated video file for a live photo
|
||||
If photo is not a live photo, returns None
|
||||
If photo is missing, returns None</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.path_raw">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">path_raw</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.path_raw" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>absolute path of associated RAW image or None if there is not one</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.person_info">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">person_info</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.person_info" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>list of PersonInfo objects for person in picture</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.persons">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">persons</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.persons" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>list of persons in picture</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.place">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">place</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.place" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns PlaceInfo object containing reverse geolocation info</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.portrait">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">portrait</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.portrait" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is a portrait, otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.project_info">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">project_info</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.project_info" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>list of AlbumInfo objects representing projects for the photo or None if no projects</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.raw_original">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">raw_original</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.raw_original" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns True if associated raw image and the raw image is selected in Photos
|
||||
via “Use RAW as Original ”
|
||||
otherwise returns False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py method">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.render_template">
|
||||
<span class="sig-name descname"><span class="pre">render_template</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">template_str</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">options</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">osxphotos.phototemplate.RenderOptions</span><span class="p"><span class="pre">]</span></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><a class="reference internal" href="_modules/osxphotos/photoinfo.html#PhotoInfo.render_template"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#osxphotos.PhotoInfo.render_template" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Renders a template string for PhotoInfo instance using PhotoTemplate</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Parameters</dt>
|
||||
<dd class="field-odd"><ul class="simple">
|
||||
<li><p><strong>template_str</strong> – a template string with fields to render</p></li>
|
||||
<li><p><strong>options</strong> – a RenderOptions instance</p></li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt class="field-even">Returns</dt>
|
||||
<dd class="field-even"><p>tuple of list of rendered strings and list of unmatched template values</p>
|
||||
</dd>
|
||||
<dt class="field-odd">Return type</dt>
|
||||
<dd class="field-odd"><p>([rendered_strings], [unmatched])</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.score">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">score</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.score" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Computed score information for a photo</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Returns</dt>
|
||||
<dd class="field-odd"><p>ScoreInfo instance</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.screenshot">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">screenshot</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.screenshot" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is an HDR photo, otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.search_info">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">search_info</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.search_info" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns SearchInfo object for photo
|
||||
only valid on Photos 5, on older libraries, returns None</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.search_info_normalized">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">search_info_normalized</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.search_info_normalized" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns SearchInfo object for photo that produces normalized results
|
||||
only valid on Photos 5, on older libraries, returns None</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.selfie">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">selfie</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.selfie" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is a selfie (front facing camera), otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.shared">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">shared</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.shared" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns True if photos is in a shared iCloud album otherwise false
|
||||
Only valid on Photos 5; returns None on older versions</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.slow_mo">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">slow_mo</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.slow_mo" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is a slow motion video, otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.time_lapse">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">time_lapse</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.time_lapse" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns True if photo is a time lapse video, otherwise False</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.title">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">title</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.title" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>name / title of picture</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.tzoffset">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">tzoffset</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.tzoffset" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>timezone offset from UTC in seconds</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.uti">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">uti</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.uti" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns Uniform Type Identifier (UTI) for the image
|
||||
for example: public.jpeg or com.apple.quicktime-movie</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.uti_edited">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">uti_edited</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.uti_edited" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns Uniform Type Identifier (UTI) for the edited image
|
||||
if the photo has been edited, otherwise None;
|
||||
for example: public.jpeg</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.uti_original">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">uti_original</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.uti_original" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns Uniform Type Identifier (UTI) for the original image
|
||||
for example: public.jpeg or com.apple.quicktime-movie</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.uti_raw">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">uti_raw</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.uti_raw" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Returns Uniform Type Identifier (UTI) for the RAW image if there is one
|
||||
for example: com.canon.cr2-raw-image
|
||||
Returns None if no associated RAW image</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.uuid">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">uuid</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.uuid" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>UUID of picture</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.visible">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">visible</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.visible" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>True if picture is visble</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py property">
|
||||
<dt class="sig sig-object py" id="osxphotos.PhotoInfo.width">
|
||||
<em class="property"><span class="pre">property</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">width</span></span><a class="headerlink" href="#osxphotos.PhotoInfo.width" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>returns width of the current photo version in pixels</p>
|
||||
</dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Search — osxphotos 0.45.8 documentation</title>
|
||||
<title>Search — osxphotos 0.46.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -3,4 +3,6 @@ osxphotos command line interface (CLI)
|
||||
|
||||
.. click:: osxphotos.cli:cli
|
||||
:prog: osxphotos
|
||||
:nested: full
|
||||
:nested: full
|
||||
|
||||
.. program-output:: python3 -m osxphotos --help
|
||||
@@ -16,7 +16,7 @@ import sys
|
||||
|
||||
import sphinx_rtd_theme
|
||||
|
||||
sys.path.insert(0, os.path.abspath(".."))
|
||||
sys.path.insert(0, os.path.abspath("../.."))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from ._constants import AlbumSortOrder
|
||||
from ._version import __version__
|
||||
from .exiftool import ExifTool
|
||||
from .export_db import ExportDB, ExportDBInMemory, ExportDBNoOp
|
||||
from .export_db import ExportDB
|
||||
from .fileutil import FileUtil, FileUtilNoOp
|
||||
from .momentinfo import MomentInfo
|
||||
from .personinfo import PersonInfo
|
||||
@@ -25,8 +25,7 @@ __all__ = [
|
||||
"CommentInfo",
|
||||
"ExifTool",
|
||||
"ExportDB",
|
||||
"ExportDBInMemory",
|
||||
"ExportDBNoOp",
|
||||
"ExportDBTemp",
|
||||
"ExportOptions",
|
||||
"ExportResults",
|
||||
"FileUtil",
|
||||
|
||||
@@ -214,8 +214,7 @@ SEARCH_CATEGORY_PHOTO_NAME = 2056
|
||||
|
||||
|
||||
# Max filename length on MacOS
|
||||
# subtract 6 chars for the lock file extension in form: ".filename.lock"
|
||||
MAX_FILENAME_LEN = 255 - 6
|
||||
MAX_FILENAME_LEN = 255
|
||||
|
||||
# Max directory name length on MacOS
|
||||
MAX_DIRNAME_LEN = 255
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.45.8"
|
||||
__version__ = "0.46.1"
|
||||
|
||||
1407
osxphotos/cli.py
1407
osxphotos/cli.py
File diff suppressed because it is too large
Load Diff
@@ -134,18 +134,12 @@ class ConfigOptions:
|
||||
filename: full path to TOML file to write; filename will be overwritten if it exists
|
||||
"""
|
||||
# todo: add overwrite and option to merge contents already in TOML file (under different [section] with new content)
|
||||
data = {}
|
||||
for attr in sorted(self._attrs.keys()):
|
||||
val = getattr(self, attr)
|
||||
if val in [False, ()]:
|
||||
val = None
|
||||
else:
|
||||
val = list(val) if type(val) == tuple else val
|
||||
|
||||
data[attr] = val
|
||||
|
||||
with open(filename, "w") as fd:
|
||||
toml.dump({self._name: data}, fd)
|
||||
toml.dump(self._get_toml_dict(), fd)
|
||||
|
||||
def write_to_str(self) -> str:
|
||||
"""Write self to TOML str"""
|
||||
return toml.dumps(self._get_toml_dict())
|
||||
|
||||
def load_from_file(self, filename, override=False):
|
||||
"""Load options from a TOML file.
|
||||
@@ -178,3 +172,17 @@ class ConfigOptions:
|
||||
|
||||
def asdict(self):
|
||||
return {attr: getattr(self, attr) for attr in sorted(self._attrs.keys())}
|
||||
|
||||
def _get_toml_dict(self):
|
||||
"""Return dict for writing to TOML file"""
|
||||
data = {}
|
||||
for attr in sorted(self._attrs.keys()):
|
||||
val = getattr(self, attr)
|
||||
if val in [False, ()]:
|
||||
val = None
|
||||
else:
|
||||
val = list(val) if type(val) == tuple else val
|
||||
|
||||
data[attr] = val
|
||||
|
||||
return {self._name: data}
|
||||
|
||||
46
osxphotos/crash_reporter.py
Normal file
46
osxphotos/crash_reporter.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""Error logger/crash reporter decorator"""
|
||||
|
||||
import datetime
|
||||
import functools
|
||||
import platform
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from rich import print
|
||||
|
||||
|
||||
def crash_reporter(filename, message, title, postamble, *extra_args):
|
||||
"""Create a crash dump file on error named filename
|
||||
|
||||
On error, create a crash dump file named filename with exception and stack trace.
|
||||
message is printed to stderr
|
||||
title is printed at beginning of crash dump file
|
||||
postamble is printed to stderr after crash dump file is created
|
||||
If extra_args is not None, any additional arguments to the function will be printed to the file.
|
||||
"""
|
||||
|
||||
def decorated(func):
|
||||
@functools.wraps(func)
|
||||
def wrapped(*args, **kwargs):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except Exception as e:
|
||||
print(message, file=sys.stderr)
|
||||
print(f"[red]{e}[/red]", file=sys.stderr)
|
||||
with open(filename, "w") as f:
|
||||
f.write(f"{title}\n")
|
||||
f.write(f"Created: {datetime.datetime.now()}\n")
|
||||
f.write(f"Python version: {sys.version}\n")
|
||||
f.write(f"Platform: {platform.platform()}\n")
|
||||
f.write(f"sys.argv: {sys.argv}\n")
|
||||
for arg in extra_args:
|
||||
f.write(f"{arg}\n")
|
||||
f.write(f"Error: {e}\n")
|
||||
traceback.print_exc(file=f)
|
||||
print(f"Crash log written to '{filename}'", file=sys.stderr)
|
||||
print(f"{postamble}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
return wrapped
|
||||
|
||||
return decorated
|
||||
File diff suppressed because it is too large
Load Diff
264
osxphotos/export_db_utils.py
Normal file
264
osxphotos/export_db_utils.py
Normal file
@@ -0,0 +1,264 @@
|
||||
""" Utility functions for working with export_db """
|
||||
|
||||
|
||||
import pathlib
|
||||
import sqlite3
|
||||
from typing import Optional, Tuple, Union
|
||||
import datetime
|
||||
import os
|
||||
|
||||
import toml
|
||||
from rich import print
|
||||
|
||||
from ._constants import OSXPHOTOS_EXPORT_DB
|
||||
from ._version import __version__
|
||||
from .export_db import OSXPHOTOS_EXPORTDB_VERSION, ExportDB
|
||||
from .fileutil import FileUtil
|
||||
from .photosdb import PhotosDB
|
||||
|
||||
__all__ = [
|
||||
"export_db_check_signatures",
|
||||
"export_db_get_last_run",
|
||||
"export_db_get_version",
|
||||
"export_db_save_config_to_file",
|
||||
"export_db_touch_files",
|
||||
"export_db_update_signatures",
|
||||
"export_db_vacuum",
|
||||
]
|
||||
|
||||
|
||||
def isotime_from_ts(ts: int) -> str:
|
||||
"""Convert timestamp to ISO 8601 time string"""
|
||||
return datetime.datetime.fromtimestamp(ts).isoformat()
|
||||
|
||||
|
||||
def export_db_get_version(
|
||||
dbfile: Union[str, pathlib.Path]
|
||||
) -> Tuple[Optional[int], Optional[int]]:
|
||||
"""returns version from export database as tuple of (osxphotos version, export_db version)"""
|
||||
conn = sqlite3.connect(str(dbfile))
|
||||
c = conn.cursor()
|
||||
row = c.execute(
|
||||
"SELECT osxphotos, exportdb FROM version ORDER BY id DESC LIMIT 1;"
|
||||
).fetchone()
|
||||
if row:
|
||||
return (row[0], row[1])
|
||||
return (None, None)
|
||||
|
||||
|
||||
def export_db_vacuum(dbfile: Union[str, pathlib.Path]) -> None:
|
||||
"""Vacuum export database"""
|
||||
conn = sqlite3.connect(str(dbfile))
|
||||
c = conn.cursor()
|
||||
c.execute("VACUUM;")
|
||||
conn.commit()
|
||||
|
||||
|
||||
def export_db_update_signatures(
|
||||
dbfile: Union[str, pathlib.Path],
|
||||
export_dir: Union[str, pathlib.Path],
|
||||
verbose: bool = False,
|
||||
dry_run: bool = False,
|
||||
) -> Tuple[int, int]:
|
||||
"""Update signatures for all files found in the export database to match what's on disk
|
||||
|
||||
Returns: tuple of (updated, skipped)
|
||||
"""
|
||||
export_dir = pathlib.Path(export_dir)
|
||||
fileutil = FileUtil
|
||||
conn = sqlite3.connect(str(dbfile))
|
||||
c = conn.cursor()
|
||||
c.execute("SELECT filepath_normalized, filepath FROM export_data;")
|
||||
rows = c.fetchall()
|
||||
updated = 0
|
||||
skipped = 0
|
||||
for row in rows:
|
||||
filepath_normalized = row[0]
|
||||
filepath = row[1]
|
||||
filepath = export_dir / filepath
|
||||
if not os.path.exists(filepath):
|
||||
skipped += 1
|
||||
if verbose:
|
||||
print(f"[dark_orange]Skipping missing file[/dark_orange]: '{filepath}'")
|
||||
continue
|
||||
updated += 1
|
||||
file_sig = fileutil.file_sig(filepath)
|
||||
if verbose:
|
||||
print(f"[green]Updating signature for[/green]: '{filepath}'")
|
||||
if not dry_run:
|
||||
c.execute(
|
||||
"UPDATE export_data SET dest_mode = ?, dest_size = ?, dest_mtime = ? WHERE filepath_normalized = ?;",
|
||||
(file_sig[0], file_sig[1], file_sig[2], filepath_normalized),
|
||||
)
|
||||
|
||||
if not dry_run:
|
||||
conn.commit()
|
||||
|
||||
return (updated, skipped)
|
||||
|
||||
|
||||
def export_db_get_last_run(
|
||||
export_db: Union[str, pathlib.Path]
|
||||
) -> Tuple[Optional[str], Optional[str]]:
|
||||
"""Get last run from export database"""
|
||||
conn = sqlite3.connect(str(export_db))
|
||||
c = conn.cursor()
|
||||
row = c.execute(
|
||||
"SELECT datetime, args FROM runs ORDER BY id DESC LIMIT 1;"
|
||||
).fetchone()
|
||||
if row:
|
||||
return row[0], row[1]
|
||||
return None, None
|
||||
|
||||
|
||||
def export_db_save_config_to_file(
|
||||
export_db: Union[str, pathlib.Path], config_file: Union[str, pathlib.Path]
|
||||
) -> None:
|
||||
"""Save export_db last run config to file"""
|
||||
export_db = pathlib.Path(export_db)
|
||||
config_file = pathlib.Path(config_file)
|
||||
conn = sqlite3.connect(str(export_db))
|
||||
c = conn.cursor()
|
||||
row = c.execute("SELECT config FROM config ORDER BY id DESC LIMIT 1;").fetchone()
|
||||
if not row:
|
||||
return ValueError("No config found in export_db")
|
||||
with config_file.open("w") as f:
|
||||
f.write(row[0])
|
||||
|
||||
|
||||
def export_db_check_signatures(
|
||||
dbfile: Union[str, pathlib.Path],
|
||||
export_dir: Union[str, pathlib.Path],
|
||||
verbose: bool = False,
|
||||
) -> Tuple[int, int, int]:
|
||||
"""Check signatures for all files found in the export database to verify what matches the on disk files
|
||||
|
||||
Returns: tuple of (updated, skipped)
|
||||
"""
|
||||
export_dir = pathlib.Path(export_dir)
|
||||
fileutil = FileUtil
|
||||
conn = sqlite3.connect(str(dbfile))
|
||||
c = conn.cursor()
|
||||
c.execute("SELECT filepath_normalized, filepath FROM export_data;")
|
||||
rows = c.fetchall()
|
||||
exportdb = ExportDB(dbfile, export_dir)
|
||||
matched = 0
|
||||
notmatched = 0
|
||||
skipped = 0
|
||||
for row in rows:
|
||||
filepath_normalized = row[0]
|
||||
filepath = row[1]
|
||||
filepath = export_dir / filepath
|
||||
if not filepath.exists():
|
||||
skipped += 1
|
||||
if verbose:
|
||||
print(f"[dark_orange]Skipping missing file[/dark_orange]: '{filepath}'")
|
||||
continue
|
||||
file_sig = fileutil.file_sig(filepath)
|
||||
file_rec = exportdb.get_file_record(filepath)
|
||||
if file_rec.dest_sig == file_sig:
|
||||
matched += 1
|
||||
if verbose:
|
||||
print(f"[green]Signatures matched[/green]: '{filepath}'")
|
||||
else:
|
||||
notmatched += 1
|
||||
if verbose:
|
||||
print(f"[deep_pink3]Signatures do not match[/deep_pink3]: '{filepath}'")
|
||||
|
||||
return (matched, notmatched, skipped)
|
||||
|
||||
|
||||
def export_db_touch_files(
|
||||
dbfile: Union[str, pathlib.Path],
|
||||
export_dir: Union[str, pathlib.Path],
|
||||
verbose: bool = False,
|
||||
dry_run: bool = False,
|
||||
) -> Tuple[int, int, int]:
|
||||
"""Touch files on disk to match the Photos library created date
|
||||
|
||||
Returns: tuple of (touched, not_touched, skipped)
|
||||
"""
|
||||
export_dir = pathlib.Path(export_dir)
|
||||
|
||||
# open and close exportdb to ensure it gets migrated
|
||||
exportdb = ExportDB(dbfile, export_dir)
|
||||
upgraded = exportdb.was_upgraded
|
||||
if upgraded and verbose:
|
||||
print(
|
||||
f"Upgraded export database {dbfile} from version {upgraded[0]} to {upgraded[1]}"
|
||||
)
|
||||
exportdb.close()
|
||||
|
||||
conn = sqlite3.connect(str(dbfile))
|
||||
c = conn.cursor()
|
||||
# get most recent config
|
||||
row = c.execute("SELECT config FROM config ORDER BY id DESC LIMIT 1;").fetchone()
|
||||
if row:
|
||||
config = toml.loads(row[0])
|
||||
try:
|
||||
photos_db_path = config["export"].get("db", None)
|
||||
except KeyError:
|
||||
photos_db_path = None
|
||||
else:
|
||||
# TODO: parse the runs table to get the last --db
|
||||
# in the mean time, photos_db_path = None will use the default library
|
||||
photos_db_path = None
|
||||
|
||||
verbose_ = print if verbose else lambda *args, **kwargs: None
|
||||
photosdb = PhotosDB(dbfile=photos_db_path, verbose=verbose_)
|
||||
exportdb = ExportDB(dbfile, export_dir)
|
||||
c.execute(
|
||||
"SELECT filepath_normalized, filepath, uuid, dest_mode, dest_size FROM export_data;"
|
||||
)
|
||||
rows = c.fetchall()
|
||||
touched = 0
|
||||
not_touched = 0
|
||||
skipped = 0
|
||||
for row in rows:
|
||||
filepath_normalized = row[0]
|
||||
filepath = row[1]
|
||||
filepath = export_dir / filepath
|
||||
uuid = row[2]
|
||||
dest_mode = row[3]
|
||||
dest_size = row[4]
|
||||
if not filepath.exists():
|
||||
skipped += 1
|
||||
if verbose:
|
||||
print(
|
||||
f"[dark_orange]Skipping missing file (not in export directory)[/dark_orange]: '{filepath}'"
|
||||
)
|
||||
continue
|
||||
|
||||
photo = photosdb.get_photo(uuid)
|
||||
if not photo:
|
||||
skipped += 1
|
||||
if verbose:
|
||||
print(
|
||||
f"[dark_orange]Skipping missing photo (did not find in Photos Library)[/dark_orange]: '{filepath}' ({uuid})"
|
||||
)
|
||||
continue
|
||||
|
||||
ts = int(photo.date.timestamp())
|
||||
stat = os.stat(str(filepath))
|
||||
mtime = stat.st_mtime
|
||||
if mtime == ts:
|
||||
not_touched += 1
|
||||
if verbose:
|
||||
print(
|
||||
f"[green]Skipping file (timestamp matches)[/green]: '{filepath}' [dodger_blue1]{isotime_from_ts(ts)} ({ts})[/dodger_blue1]"
|
||||
)
|
||||
continue
|
||||
|
||||
touched += 1
|
||||
if verbose:
|
||||
print(
|
||||
f"[deep_pink3]Touching file[/deep_pink3]: '{filepath}' "
|
||||
f"[dodger_blue1]{isotime_from_ts(mtime)} ({mtime}) -> {isotime_from_ts(ts)} ({ts})[/dodger_blue1]"
|
||||
)
|
||||
|
||||
if not dry_run:
|
||||
os.utime(str(filepath), (ts, ts))
|
||||
rec = exportdb.get_file_record(filepath)
|
||||
rec.dest_sig = (dest_mode, dest_size, ts)
|
||||
|
||||
return (touched, not_touched, skipped)
|
||||
@@ -143,7 +143,7 @@ class FileUtilMacOS(FileUtilABC):
|
||||
@classmethod
|
||||
def utime(cls, path, times):
|
||||
"""Set the access and modified time of path."""
|
||||
os.utime(path, times)
|
||||
os.utime(path, times=times)
|
||||
|
||||
@classmethod
|
||||
def cmp(cls, f1, f2, mtime1=None):
|
||||
@@ -187,7 +187,7 @@ class FileUtilMacOS(FileUtilABC):
|
||||
|
||||
@classmethod
|
||||
def file_sig(cls, f1):
|
||||
"""return os.stat signature for file f1"""
|
||||
"""return os.stat signature for file f1 as tuple of (mode, size, mtime)"""
|
||||
return cls._sig(os.stat(f1))
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
""" utility functions for validating/sanitizing path components """
|
||||
|
||||
import re
|
||||
|
||||
import pathvalidate
|
||||
|
||||
from ._constants import MAX_DIRNAME_LEN, MAX_FILENAME_LEN
|
||||
|
||||
__all__ = [
|
||||
"is_valid_filepath",
|
||||
"sanitize_dirname",
|
||||
"sanitize_filename",
|
||||
"sanitize_filepath",
|
||||
"sanitize_filestem_with_count",
|
||||
"is_valid_filepath",
|
||||
"sanitize_filename",
|
||||
"sanitize_dirname",
|
||||
"sanitize_pathpart",
|
||||
]
|
||||
|
||||
@@ -56,26 +53,6 @@ def sanitize_filename(filename, replacement=":"):
|
||||
return filename
|
||||
|
||||
|
||||
def sanitize_filestem_with_count(file_stem: str, file_suffix: str) -> str:
|
||||
"""Sanitize a filestem that may end in (1), (2), etc. to ensure it + file_suffix doesn't exceed MAX_FILENAME_LEN"""
|
||||
filename_len = len(file_stem) + len(file_suffix)
|
||||
if filename_len <= MAX_FILENAME_LEN:
|
||||
return file_stem
|
||||
|
||||
drop = filename_len - MAX_FILENAME_LEN
|
||||
match = re.match(r"(.*)(\(\d+\))$", file_stem)
|
||||
if not match:
|
||||
# filename doesn't end in (1), (2), etc.
|
||||
# truncate filename to MAX_FILENAME_LEN
|
||||
return file_stem[:-drop]
|
||||
|
||||
# filename ends in (1), (2), etc.
|
||||
file_stem = match.group(1)
|
||||
file_count = match.group(2)
|
||||
file_stem = file_stem[:-drop]
|
||||
return f"{file_stem}{file_count}"
|
||||
|
||||
|
||||
def sanitize_dirname(dirname, replacement=":"):
|
||||
"""replace any illegal characters in a directory name and truncate directory name if needed
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ from ._constants import (
|
||||
from ._version import __version__
|
||||
from .datetime_utils import datetime_tz_to_utc
|
||||
from .exiftool import ExifTool, exiftool_can_write
|
||||
from .export_db import ExportDB_ABC, ExportDBNoOp
|
||||
from .export_db import ExportDB, ExportDBTemp
|
||||
from .fileutil import FileUtil
|
||||
from .photokit import (
|
||||
PHOTOS_VERSION_CURRENT,
|
||||
@@ -81,8 +81,10 @@ class ExportOptions:
|
||||
exiftool_flags (list of str): optional list of flags to pass to exiftool when using exiftool option, e.g ["-m", "-F"]
|
||||
exiftool: (bool, default = False): if True, will use exiftool to write metadata to export file
|
||||
export_as_hardlink: (bool, default=False): if True, will hardlink files instead of copying them
|
||||
export_db: (ExportDB_ABC): instance of a class that conforms to ExportDB_ABC with methods for getting/setting data related to exported files to compare update state
|
||||
export_db: (ExportDB): instance of a class that conforms to ExportDB with methods for getting/setting data related to exported files to compare update state
|
||||
face_regions: (bool, default=True): if True, will export face regions
|
||||
fileutil: (FileUtilABC): class that conforms to FileUtilABC with various file utilities
|
||||
force_update: (bool, default=False): if True, will export photo if any metadata has changed but export otherwise would not be triggered (e.g. metadata changed but not using exiftool)
|
||||
ignore_date_modified (bool): for use with sidecar and exiftool; if True, sets EXIF:ModifyDate to EXIF:DateTimeOriginal even if date_modified is set
|
||||
ignore_signature (bool, default=False): ignore file signature when used with update (look only at filename)
|
||||
increment (bool, default=True): if True, will increment file name until a non-existant name is found if overwrite=False and increment=False, export will fail if destination file already exists
|
||||
@@ -126,8 +128,10 @@ class ExportOptions:
|
||||
exiftool_flags: Optional[List] = None
|
||||
exiftool: bool = False
|
||||
export_as_hardlink: bool = False
|
||||
export_db: Optional[ExportDB_ABC] = None
|
||||
export_db: Optional[ExportDB] = None
|
||||
face_regions: bool = True
|
||||
fileutil: Optional[FileUtil] = None
|
||||
force_update: bool = False
|
||||
ignore_date_modified: bool = False
|
||||
ignore_signature: bool = False
|
||||
increment: bool = True
|
||||
@@ -160,6 +164,12 @@ class ExportOptions:
|
||||
def asdict(self):
|
||||
return asdict(self)
|
||||
|
||||
@property
|
||||
def bit_flags(self):
|
||||
"""Return bit flags representing options that affect export"""
|
||||
# currently only exiftool makes a difference
|
||||
return self.exiftool << 1
|
||||
|
||||
|
||||
class StagedFiles:
|
||||
"""Represents files staged for export"""
|
||||
@@ -347,34 +357,6 @@ class ExportResults:
|
||||
+ ")"
|
||||
)
|
||||
|
||||
def asdict(self):
|
||||
"""Return dict instance of class"""
|
||||
return {
|
||||
"exported": self.exported,
|
||||
"new": self.new,
|
||||
"updated": self.updated,
|
||||
"skipped": self.skipped,
|
||||
"exif_updated": self.exif_updated,
|
||||
"touched": self.touched,
|
||||
"to_touch": self.to_touch,
|
||||
"converted_to_jpeg": self.converted_to_jpeg,
|
||||
"sidecar_json_written": self.sidecar_json_written,
|
||||
"sidecar_json_skipped": self.sidecar_json_skipped,
|
||||
"sidecar_exiftool_written": self.sidecar_exiftool_written,
|
||||
"sidecar_exiftool_skipped": self.sidecar_exiftool_skipped,
|
||||
"sidecar_xmp_written": self.sidecar_xmp_written,
|
||||
"sidecar_xmp_skipped": self.sidecar_xmp_skipped,
|
||||
"missing": self.missing,
|
||||
"error": self.error,
|
||||
"exiftool_warning": self.exiftool_warning,
|
||||
"exiftool_error": self.exiftool_error,
|
||||
"deleted_files": self.deleted_files,
|
||||
"deleted_directories": self.deleted_directories,
|
||||
"exported_album": self.exported_album,
|
||||
"skipped_album": self.skipped_album,
|
||||
"missing_album": self.missing_album,
|
||||
}
|
||||
|
||||
|
||||
class PhotoExporter:
|
||||
def __init__(self, photo: "PhotoInfo"):
|
||||
@@ -427,8 +409,8 @@ class PhotoExporter:
|
||||
"Cannot use export_as_hardlink with download_missing or use_photos_export"
|
||||
)
|
||||
|
||||
# when called from export(), won't get an export_db, so use no-op version
|
||||
options.export_db = options.export_db or ExportDBNoOp()
|
||||
# when called from export(), won't get an export_db, so use temp version
|
||||
options.export_db = options.export_db or ExportDBTemp()
|
||||
|
||||
# ensure there's a FileUtil class to use
|
||||
options.fileutil = options.fileutil or FileUtil
|
||||
@@ -467,6 +449,7 @@ class PhotoExporter:
|
||||
|
||||
# get the right destination path depending on options.update, etc.
|
||||
dest = self._get_dest_path(src, dest, options)
|
||||
|
||||
self._render_options.filepath = str(dest)
|
||||
all_results = ExportResults()
|
||||
|
||||
@@ -477,98 +460,112 @@ class PhotoExporter:
|
||||
dest,
|
||||
options=options,
|
||||
)
|
||||
else:
|
||||
verbose(
|
||||
f"Skipping missing {'edited' if options.edited else 'original'} photo {self.photo.original_filename} ({self.photo.uuid})"
|
||||
)
|
||||
all_results.missing.append(dest)
|
||||
|
||||
# copy live photo associated .mov if requested
|
||||
if (
|
||||
export_original
|
||||
and options.live_photo
|
||||
and self.photo.live_photo
|
||||
and staged_files.original_live
|
||||
):
|
||||
if export_original and options.live_photo and self.photo.live_photo:
|
||||
live_name = dest.parent / f"{dest.stem}.mov"
|
||||
src_live = staged_files.original_live
|
||||
all_results += self._export_photo(
|
||||
src_live,
|
||||
live_name,
|
||||
# don't try to convert the live photo
|
||||
options=dataclasses.replace(options, convert_to_jpeg=False),
|
||||
)
|
||||
if staged_files.original_live:
|
||||
src_live = staged_files.original_live
|
||||
all_results += self._export_photo(
|
||||
src_live,
|
||||
live_name,
|
||||
# don't try to convert the live photo
|
||||
options=dataclasses.replace(options, convert_to_jpeg=False),
|
||||
)
|
||||
else:
|
||||
verbose(
|
||||
f"Skipping missing live photo for {self.photo.original_filename} ({self.photo.uuid})"
|
||||
)
|
||||
all_results.missing.append(live_name)
|
||||
|
||||
if (
|
||||
export_edited
|
||||
and options.live_photo
|
||||
and self.photo.live_photo
|
||||
and staged_files.edited_live
|
||||
):
|
||||
if export_edited and options.live_photo and self.photo.live_photo:
|
||||
live_name = dest.parent / f"{dest.stem}.mov"
|
||||
src_live = staged_files.edited_live
|
||||
all_results += self._export_photo(
|
||||
src_live,
|
||||
live_name,
|
||||
# don't try to convert the live photo
|
||||
options=dataclasses.replace(options, convert_to_jpeg=False),
|
||||
)
|
||||
if staged_files.edited_live:
|
||||
src_live = staged_files.edited_live
|
||||
all_results += self._export_photo(
|
||||
src_live,
|
||||
live_name,
|
||||
# don't try to convert the live photo
|
||||
options=dataclasses.replace(options, convert_to_jpeg=False),
|
||||
)
|
||||
else:
|
||||
verbose(
|
||||
f"Skipping missing edited live photo for {self.photo.original_filename} ({self.photo.uuid})"
|
||||
)
|
||||
all_results.missing.append(live_name)
|
||||
|
||||
# copy associated RAW image if requested
|
||||
if options.raw_photo and self.photo.has_raw and staged_files.raw:
|
||||
raw_path = pathlib.Path(staged_files.raw)
|
||||
raw_ext = raw_path.suffix
|
||||
raw_name = dest.parent / f"{dest.stem}{raw_ext}"
|
||||
all_results += self._export_photo(
|
||||
raw_path,
|
||||
raw_name,
|
||||
options=options,
|
||||
)
|
||||
if options.raw_photo and self.photo.has_raw:
|
||||
if staged_files.raw:
|
||||
raw_path = pathlib.Path(staged_files.raw)
|
||||
raw_ext = raw_path.suffix
|
||||
raw_name = dest.parent / f"{dest.stem}{raw_ext}"
|
||||
all_results += self._export_photo(
|
||||
raw_path,
|
||||
raw_name,
|
||||
options=options,
|
||||
)
|
||||
else:
|
||||
# guess at most likely raw name
|
||||
raw_ext = get_preferred_uti_extension(self.photo.uti_raw) or "raw"
|
||||
raw_name = dest.parent / f"{dest.stem}.{raw_ext}"
|
||||
all_results.missing.append(raw_name)
|
||||
verbose(
|
||||
f"Skipping missing raw photo for {self.photo.original_filename} ({self.photo.uuid})"
|
||||
)
|
||||
|
||||
# copy preview image if requested
|
||||
if options.preview and staged_files.preview:
|
||||
# Photos keeps multiple different derivatives and path_derivatives returns list of them
|
||||
# first derivative is the largest so export that one
|
||||
preview_path = pathlib.Path(staged_files.preview)
|
||||
preview_ext = preview_path.suffix
|
||||
preview_name = (
|
||||
dest.parent / f"{dest.stem}{options.preview_suffix}{preview_ext}"
|
||||
)
|
||||
# if original is missing, the filename won't have been incremented so
|
||||
# need to check here to make sure there aren't duplicate preview files in
|
||||
# the export directory
|
||||
preview_name = (
|
||||
preview_name
|
||||
if options.overwrite or options.update
|
||||
else pathlib.Path(increment_filename(preview_name, lock=True))
|
||||
)
|
||||
all_results += self._export_photo(
|
||||
preview_path,
|
||||
preview_name,
|
||||
options=options,
|
||||
)
|
||||
if options.preview:
|
||||
if staged_files.preview:
|
||||
# Photos keeps multiple different derivatives and path_derivatives returns list of them
|
||||
# first derivative is the largest so export that one
|
||||
preview_path = pathlib.Path(staged_files.preview)
|
||||
preview_ext = preview_path.suffix
|
||||
preview_name = (
|
||||
dest.parent / f"{dest.stem}{options.preview_suffix}{preview_ext}"
|
||||
)
|
||||
# if original is missing, the filename won't have been incremented so
|
||||
# need to check here to make sure there aren't duplicate preview files in
|
||||
# the export directory
|
||||
preview_name = (
|
||||
preview_name
|
||||
if any([options.overwrite, options.update, options.force_update])
|
||||
else pathlib.Path(increment_filename(preview_name))
|
||||
)
|
||||
all_results += self._export_photo(
|
||||
preview_path,
|
||||
preview_name,
|
||||
options=options,
|
||||
)
|
||||
else:
|
||||
# don't know what actual preview suffix would be but most likely jpeg
|
||||
preview_name = dest.parent / f"{dest.stem}{options.preview_suffix}.jpeg"
|
||||
all_results.missing.append(preview_name)
|
||||
verbose(
|
||||
f"Skipping missing preview photo for {self.photo.original_filename} ({self.photo.uuid})"
|
||||
)
|
||||
|
||||
all_results += self._write_sidecar_files(dest=dest, options=options)
|
||||
|
||||
if options.touch_file:
|
||||
all_results += self._touch_files(all_results, options)
|
||||
|
||||
# if src was missing, there will be a lock file for dest that needs cleaning up
|
||||
try:
|
||||
lock_file = dest.parent / f".{dest.name}.lock"
|
||||
self.fileutil.unlink(lock_file)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return all_results
|
||||
|
||||
def _touch_files(
|
||||
self, results: ExportResults, options: ExportOptions
|
||||
) -> ExportResults:
|
||||
"""touch file date/time to match photo creation date/time"""
|
||||
def _touch_files(self, touch_files: List, options: ExportOptions) -> ExportResults:
|
||||
"""touch file date/time to match photo creation date/time; only touches files if needed"""
|
||||
fileutil = options.fileutil
|
||||
touch_files = set(results.to_touch)
|
||||
touch_results = ExportResults()
|
||||
for touch_file in touch_files:
|
||||
touch_results = []
|
||||
for touch_file in set(touch_files):
|
||||
ts = int(self.photo.date.timestamp())
|
||||
fileutil.utime(touch_file, (ts, ts))
|
||||
touch_results.touched.append(touch_file)
|
||||
return touch_results
|
||||
stat = os.stat(touch_file)
|
||||
if stat.st_mtime != ts:
|
||||
if not options.dry_run:
|
||||
fileutil.utime(touch_file, (ts, ts))
|
||||
touch_results.append(touch_file)
|
||||
return ExportResults(touched=touch_results)
|
||||
|
||||
def _get_edited_filename(self, original_filename):
|
||||
"""Return the filename for the exported edited photo
|
||||
@@ -600,7 +597,7 @@ class PhotoExporter:
|
||||
|
||||
# if overwrite==False and #increment==False, export should fail if file exists
|
||||
if dest.exists() and not any(
|
||||
[options.increment, options.update, options.overwrite]
|
||||
[options.increment, options.update, options.force_update, options.overwrite]
|
||||
):
|
||||
raise FileExistsError(
|
||||
f"destination exists ({dest}); overwrite={options.overwrite}, increment={options.increment}"
|
||||
@@ -612,26 +609,16 @@ class PhotoExporter:
|
||||
# e.g. exporting sidecar for file1.png and file1.jpeg
|
||||
# if file1.png exists and exporting file1.jpeg,
|
||||
# dest will be file1 (1).jpeg even though file1.jpeg doesn't exist to prevent sidecar collision
|
||||
if options.increment and not options.update and not options.overwrite:
|
||||
return pathlib.Path(
|
||||
increment_filename(dest, lock=True, dry_run=options.dry_run)
|
||||
)
|
||||
if options.increment and not any(
|
||||
[options.update, options.force_update, options.overwrite]
|
||||
):
|
||||
return pathlib.Path(increment_filename(dest))
|
||||
|
||||
# if update and file exists, need to check to see if it's the write file by checking export db
|
||||
if options.update and dest.exists() and src:
|
||||
# if update and file exists, need to check to see if it's the right file by checking export db
|
||||
if (options.update or options.force_update) and dest.exists() and src:
|
||||
export_db = options.export_db
|
||||
fileutil = options.fileutil
|
||||
# destination exists, check to see if destination is the right UUID
|
||||
dest_uuid = export_db.get_uuid_for_file(dest)
|
||||
if dest_uuid is None and fileutil.cmp(src, dest):
|
||||
# might be exporting into a pre-ExportDB folder or the DB got deleted
|
||||
dest_uuid = self.photo.uuid
|
||||
export_db.set_data(
|
||||
filename=dest,
|
||||
uuid=self.photo.uuid,
|
||||
orig_stat=fileutil.file_sig(dest),
|
||||
info_json=self.photo.json(),
|
||||
)
|
||||
if dest_uuid != self.photo.uuid:
|
||||
# not the right file, find the right one
|
||||
# find files that match "dest_name (*.ext" (e.g. "dest_name (1).jpg", "dest_name (2).jpg)", ...)
|
||||
@@ -646,25 +633,64 @@ class PhotoExporter:
|
||||
if dest_uuid == self.photo.uuid:
|
||||
dest = pathlib.Path(file_)
|
||||
break
|
||||
elif dest_uuid is None and fileutil.cmp(src, file_):
|
||||
# files match, update the UUID
|
||||
dest = pathlib.Path(file_)
|
||||
export_db.set_data(
|
||||
filename=dest,
|
||||
uuid=self.photo.uuid,
|
||||
orig_stat=fileutil.file_sig(dest),
|
||||
info_json=self.photo.json(),
|
||||
)
|
||||
break
|
||||
else:
|
||||
# increment the destination file
|
||||
dest = pathlib.Path(
|
||||
increment_filename(dest, lock=True, dry_run=options.dry_run)
|
||||
)
|
||||
dest = pathlib.Path(increment_filename(dest))
|
||||
|
||||
# either dest was updated in the if clause above or not updated at all
|
||||
return dest
|
||||
|
||||
def _should_update_photo(
|
||||
self, src: pathlib.Path, dest: pathlib.Path, options: ExportOptions
|
||||
) -> bool:
|
||||
"""Return True if photo should be updated, else False"""
|
||||
export_db = options.export_db
|
||||
fileutil = options.fileutil
|
||||
|
||||
file_record = export_db.get_file_record(dest)
|
||||
|
||||
if not file_record:
|
||||
# photo doesn't exist in database, should update
|
||||
return True
|
||||
|
||||
if options.export_as_hardlink and not dest.samefile(src):
|
||||
# different files, should update
|
||||
return True
|
||||
|
||||
if not options.export_as_hardlink and dest.samefile(src):
|
||||
# same file but not exporting as hardlink, should update
|
||||
return True
|
||||
|
||||
if not options.ignore_signature and not fileutil.cmp_file_sig(
|
||||
dest, file_record.dest_sig
|
||||
):
|
||||
# destination file doesn't match what was last exported
|
||||
return True
|
||||
|
||||
if file_record.export_options != options.bit_flags:
|
||||
# exporting with different set of options (e.g. exiftool), should update
|
||||
# need to check this before exiftool in case exiftool options are different
|
||||
# and export database is missing; this will always be True if database is missing
|
||||
# as it'll be None and bit_flags will be an int
|
||||
return True
|
||||
|
||||
if options.exiftool:
|
||||
current_exifdata = self._exiftool_json_sidecar(options=options)
|
||||
return current_exifdata != file_record.exifdata
|
||||
|
||||
if options.edited and not fileutil.cmp_file_sig(src, file_record.src_sig):
|
||||
# edited file in Photos doesn't match what was last exported
|
||||
return True
|
||||
|
||||
if options.force_update:
|
||||
current_digest = hexdigest(self.photo.json())
|
||||
if current_digest != file_record.digest:
|
||||
# metadata in Photos changed, force update
|
||||
return True
|
||||
|
||||
# photo should not be updated
|
||||
return False
|
||||
|
||||
def _stage_photos_for_export(self, options: ExportOptions) -> StagedFiles:
|
||||
"""Stages photos for export
|
||||
|
||||
@@ -750,7 +776,7 @@ class PhotoExporter:
|
||||
# export live_photo .mov file?
|
||||
live_photo = bool(options.live_photo and self.photo.live_photo)
|
||||
|
||||
overwrite = options.overwrite or options.update
|
||||
overwrite = any([options.overwrite, options.update, options.force_update])
|
||||
|
||||
# figure out which photo version to request
|
||||
if options.edited or self.photo.shared:
|
||||
@@ -854,13 +880,11 @@ class PhotoExporter:
|
||||
raise ValueError("Edited version requested but photo has no adjustments")
|
||||
|
||||
dest = self._temp_dir_path / self.photo.original_filename
|
||||
dest = pathlib.Path(
|
||||
increment_filename(dest, lock=True, dry_run=options.dry_run)
|
||||
)
|
||||
dest = pathlib.Path(increment_filename(dest))
|
||||
|
||||
# export live_photo .mov file?
|
||||
live_photo = bool(options.live_photo and self.photo.live_photo)
|
||||
overwrite = options.overwrite or options.update
|
||||
overwrite = any([options.overwrite, options.update, options.force_update])
|
||||
edited_version = options.edited or self.photo.shared
|
||||
# shared photos (in shared albums) show up as not having adjustments (not edited)
|
||||
# but Photos is unable to export the "original" as only a jpeg copy is shared in iCloud
|
||||
@@ -956,7 +980,7 @@ class PhotoExporter:
|
||||
"""Copies filepath to a temp file preserving access and modification times"""
|
||||
filepath = pathlib.Path(filepath)
|
||||
dest = self._temp_dir_path / filepath.name
|
||||
dest = increment_filename(dest, lock=True)
|
||||
dest = increment_filename(dest)
|
||||
self.fileutil.copy(filepath, dest)
|
||||
stat = os.stat(filepath)
|
||||
self.fileutil.utime(dest, (stat.st_atime, stat.st_mtime))
|
||||
@@ -1000,11 +1024,8 @@ class PhotoExporter:
|
||||
update_updated_files = []
|
||||
update_new_files = []
|
||||
update_skipped_files = [] # skip files that are already up to date
|
||||
touched_files = []
|
||||
converted_to_jpeg_files = []
|
||||
exif_results = ExportResults()
|
||||
converted_stat = None
|
||||
edited_stat = None
|
||||
|
||||
dest_str = str(dest)
|
||||
dest_exists = dest.exists()
|
||||
@@ -1012,95 +1033,29 @@ class PhotoExporter:
|
||||
fileutil = options.fileutil
|
||||
export_db = options.export_db
|
||||
|
||||
if options.update: # updating
|
||||
cmp_touch, cmp_orig = False, False
|
||||
if options.update or options.force_update: # updating
|
||||
if dest_exists:
|
||||
# update, destination exists, but we might not need to replace it...
|
||||
if options.ignore_signature:
|
||||
cmp_orig = True
|
||||
cmp_touch = fileutil.cmp(
|
||||
src, dest, mtime1=int(self.photo.date.timestamp())
|
||||
)
|
||||
elif options.exiftool:
|
||||
sig_exif = export_db.get_stat_exif_for_file(dest_str)
|
||||
cmp_orig = fileutil.cmp_file_sig(dest_str, sig_exif)
|
||||
sig_exif = (
|
||||
sig_exif[0],
|
||||
sig_exif[1],
|
||||
int(self.photo.date.timestamp()),
|
||||
)
|
||||
cmp_touch = fileutil.cmp_file_sig(dest_str, sig_exif)
|
||||
elif options.convert_to_jpeg:
|
||||
sig_converted = export_db.get_stat_converted_for_file(dest_str)
|
||||
cmp_orig = fileutil.cmp_file_sig(dest_str, sig_converted)
|
||||
sig_converted = (
|
||||
sig_converted[0],
|
||||
sig_converted[1],
|
||||
int(self.photo.date.timestamp()),
|
||||
)
|
||||
cmp_touch = fileutil.cmp_file_sig(dest_str, sig_converted)
|
||||
else:
|
||||
cmp_orig = fileutil.cmp(src, dest)
|
||||
cmp_touch = fileutil.cmp(
|
||||
src, dest, mtime1=int(self.photo.date.timestamp())
|
||||
)
|
||||
|
||||
sig_cmp = cmp_touch if options.touch_file else cmp_orig
|
||||
|
||||
if options.edited:
|
||||
# requested edited version of photo
|
||||
# need to see if edited version in Photos library has changed
|
||||
# (e.g. it's been edited again)
|
||||
sig_edited = export_db.get_stat_edited_for_file(dest_str)
|
||||
cmp_edited = (
|
||||
fileutil.cmp_file_sig(src, sig_edited)
|
||||
if sig_edited != (None, None, None)
|
||||
else False
|
||||
)
|
||||
sig_cmp = sig_cmp and cmp_edited
|
||||
|
||||
if (options.export_as_hardlink and dest.samefile(src)) or (
|
||||
not options.export_as_hardlink
|
||||
and not dest.samefile(src)
|
||||
and sig_cmp
|
||||
):
|
||||
# destination exists and signatures match, skip it
|
||||
update_skipped_files.append(dest_str)
|
||||
elif options.touch_file and cmp_orig and not cmp_touch:
|
||||
# destination exists, signature matches original but does not match expected touch time
|
||||
# skip exporting but update touch time
|
||||
update_skipped_files.append(dest_str)
|
||||
touched_files.append(dest_str)
|
||||
elif not options.touch_file and cmp_touch and not cmp_orig:
|
||||
# destination exists, signature matches expected touch but not original
|
||||
# user likely exported with touch_file and is now exporting without touch_file
|
||||
# don't update the file because it's same but leave touch time
|
||||
update_skipped_files.append(dest_str)
|
||||
else:
|
||||
# destination exists but is different
|
||||
if self._should_update_photo(src, dest, options):
|
||||
update_updated_files.append(dest_str)
|
||||
if options.touch_file:
|
||||
touched_files.append(dest_str)
|
||||
else:
|
||||
update_skipped_files.append(dest_str)
|
||||
else:
|
||||
# update, destination doesn't exist (new file)
|
||||
update_new_files.append(dest_str)
|
||||
if options.touch_file:
|
||||
touched_files.append(dest_str)
|
||||
else:
|
||||
# not update, export the file
|
||||
exported_files.append(dest_str)
|
||||
if options.touch_file:
|
||||
sig = fileutil.file_sig(src)
|
||||
sig = (sig[0], sig[1], int(self.photo.date.timestamp()))
|
||||
if not fileutil.cmp_file_sig(src, sig):
|
||||
touched_files.append(dest_str)
|
||||
|
||||
if not update_skipped_files:
|
||||
# have file to export
|
||||
edited_stat = (
|
||||
fileutil.file_sig(src) if options.edited else (None, None, None)
|
||||
export_files = update_new_files + update_updated_files + exported_files
|
||||
for export_dest in export_files:
|
||||
# set src_sig before any modifications by convert_to_jpeg or exiftool
|
||||
export_record = export_db.create_or_get_file_record(
|
||||
export_dest, self.photo.uuid
|
||||
)
|
||||
if dest_exists and (options.update or options.overwrite):
|
||||
export_record.src_sig = fileutil.file_sig(src)
|
||||
if dest_exists and any(
|
||||
[options.overwrite, options.update, options.force_update]
|
||||
):
|
||||
# need to remove the destination first
|
||||
try:
|
||||
fileutil.unlink(dest)
|
||||
@@ -1121,15 +1076,12 @@ class PhotoExporter:
|
||||
# convert to a temp file before copying
|
||||
tmp_file = increment_filename(
|
||||
self._temp_dir_path
|
||||
/ f"{pathlib.Path(src).stem}_converted_to_jpeg.jpeg",
|
||||
lock=True,
|
||||
dry_run=options.dry_run,
|
||||
/ f"{pathlib.Path(src).stem}_converted_to_jpeg.jpeg"
|
||||
)
|
||||
fileutil.convert_to_jpeg(
|
||||
src, tmp_file, compression_quality=options.jpeg_quality
|
||||
)
|
||||
src = tmp_file
|
||||
converted_stat = fileutil.file_sig(tmp_file)
|
||||
converted_to_jpeg_files.append(dest_str)
|
||||
|
||||
if options.exiftool:
|
||||
@@ -1145,30 +1097,7 @@ class PhotoExporter:
|
||||
f"Error copying file {src} to {dest_str}: {e} ({lineno(__file__)})"
|
||||
) from e
|
||||
|
||||
export_db.set_data(
|
||||
filename=dest_str,
|
||||
uuid=self.photo.uuid,
|
||||
orig_stat=fileutil.file_sig(dest_str),
|
||||
converted_stat=converted_stat,
|
||||
edited_stat=edited_stat,
|
||||
info_json=self.photo.json(),
|
||||
)
|
||||
|
||||
# clean up lock files
|
||||
for file_ in set(
|
||||
converted_to_jpeg_files
|
||||
+ exported_files
|
||||
+ update_new_files
|
||||
+ update_updated_files
|
||||
):
|
||||
try:
|
||||
file_ = pathlib.Path(file_)
|
||||
lock_file = str(file_.parent / f".{file_.name}.lock")
|
||||
fileutil.unlink(lock_file)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return ExportResults(
|
||||
results = ExportResults(
|
||||
converted_to_jpeg=converted_to_jpeg_files,
|
||||
error=exif_results.error,
|
||||
exif_updated=exif_results.exif_updated,
|
||||
@@ -1177,10 +1106,34 @@ class PhotoExporter:
|
||||
exported=exported_files + update_new_files + update_updated_files,
|
||||
new=update_new_files,
|
||||
skipped=update_skipped_files,
|
||||
to_touch=touched_files,
|
||||
updated=update_updated_files,
|
||||
)
|
||||
|
||||
# touch files if needed
|
||||
if options.touch_file:
|
||||
results += self._touch_files(
|
||||
exported_files
|
||||
+ update_new_files
|
||||
+ update_updated_files
|
||||
+ update_skipped_files,
|
||||
options,
|
||||
)
|
||||
|
||||
# set data in the database
|
||||
with export_db.create_or_get_file_record(dest_str, self.photo.uuid) as rec:
|
||||
photoinfo = self.photo.json()
|
||||
rec.photoinfo = photoinfo
|
||||
rec.export_options = options.bit_flags
|
||||
# don't set src_sig as that is set above before any modifications by convert_to_jpeg or exiftool
|
||||
if not options.ignore_signature:
|
||||
rec.dest_sig = fileutil.file_sig(dest)
|
||||
if options.exiftool:
|
||||
rec.exifdata = self._exiftool_json_sidecar(options)
|
||||
if options.force_update:
|
||||
rec.digest = hexdigest(photoinfo)
|
||||
|
||||
return results
|
||||
|
||||
def _write_sidecar_files(
|
||||
self,
|
||||
dest: pathlib.Path,
|
||||
@@ -1261,16 +1214,21 @@ class PhotoExporter:
|
||||
sidecar_type = data[4]
|
||||
|
||||
sidecar_digest = hexdigest(sidecar_str)
|
||||
old_sidecar_digest, sidecar_sig = export_db.get_sidecar_for_file(
|
||||
sidecar_filename
|
||||
sidecar_record = export_db.create_or_get_file_record(
|
||||
sidecar_filename, self.photo.uuid
|
||||
)
|
||||
write_sidecar = (
|
||||
not options.update
|
||||
or (options.update and not sidecar_filename.exists())
|
||||
not (options.update or options.force_update)
|
||||
or (
|
||||
options.update
|
||||
and (sidecar_digest != old_sidecar_digest)
|
||||
or not fileutil.cmp_file_sig(sidecar_filename, sidecar_sig)
|
||||
(options.update or options.force_update)
|
||||
and not sidecar_filename.exists()
|
||||
)
|
||||
or (
|
||||
(options.update or options.force_update)
|
||||
and (sidecar_digest != sidecar_record.digest)
|
||||
or not fileutil.cmp_file_sig(
|
||||
sidecar_filename, sidecar_record.dest_sig
|
||||
)
|
||||
)
|
||||
)
|
||||
if write_sidecar:
|
||||
@@ -1278,16 +1236,13 @@ class PhotoExporter:
|
||||
files_written.append(str(sidecar_filename))
|
||||
if not options.dry_run:
|
||||
self._write_sidecar(sidecar_filename, sidecar_str)
|
||||
export_db.set_sidecar_for_file(
|
||||
sidecar_filename,
|
||||
sidecar_digest,
|
||||
fileutil.file_sig(sidecar_filename),
|
||||
)
|
||||
sidecar_record.digest = sidecar_digest
|
||||
sidecar_record.dest_sig = fileutil.file_sig(sidecar_filename)
|
||||
else:
|
||||
verbose(f"Skipped up to date {sidecar_type} sidecar {sidecar_filename}")
|
||||
files_skipped.append(str(sidecar_filename))
|
||||
|
||||
return ExportResults(
|
||||
results = ExportResults(
|
||||
sidecar_json_written=sidecar_json_files_written,
|
||||
sidecar_json_skipped=sidecar_json_files_skipped,
|
||||
sidecar_exiftool_written=sidecar_exiftool_files_written,
|
||||
@@ -1296,6 +1251,26 @@ class PhotoExporter:
|
||||
sidecar_xmp_skipped=sidecar_xmp_files_skipped,
|
||||
)
|
||||
|
||||
if options.touch_file:
|
||||
all_sidecars = (
|
||||
sidecar_json_files_written
|
||||
+ sidecar_exiftool_files_written
|
||||
+ sidecar_xmp_files_written
|
||||
+ sidecar_json_files_skipped
|
||||
+ sidecar_exiftool_files_skipped
|
||||
+ sidecar_xmp_files_skipped
|
||||
)
|
||||
results += self._touch_files(all_sidecars, options)
|
||||
|
||||
# update destination signatures in database
|
||||
for sidecar_filename in all_sidecars:
|
||||
sidecar_record = export_db.create_or_get_file_record(
|
||||
sidecar_filename, self.photo.uuid
|
||||
)
|
||||
sidecar_record.dest_sig = fileutil.file_sig(sidecar_filename)
|
||||
|
||||
return results
|
||||
|
||||
def _write_exif_metadata_to_file(
|
||||
self,
|
||||
src,
|
||||
@@ -1310,10 +1285,7 @@ class PhotoExporter:
|
||||
local machine prior to being copied to the export destination which may be on a
|
||||
network drive or other slower external storage."""
|
||||
|
||||
export_db = options.export_db
|
||||
fileutil = options.fileutil
|
||||
verbose = options.verbose or self._verbose
|
||||
|
||||
exiftool_results = ExportResults()
|
||||
|
||||
# don't try to write if unsupported file type for exiftool
|
||||
@@ -1325,26 +1297,35 @@ class PhotoExporter:
|
||||
)
|
||||
)
|
||||
# set file signature so the file doesn't get re-exported with --update
|
||||
export_db.set_data(
|
||||
dest,
|
||||
uuid=self.photo.uuid,
|
||||
exif_stat=fileutil.file_sig(src),
|
||||
exif_json=self._exiftool_json_sidecar(options=options),
|
||||
)
|
||||
return exiftool_results
|
||||
|
||||
# determine if we need to write the exif metadata
|
||||
# if we are not updating, we always write
|
||||
# else, need to check the database to determine if we need to write
|
||||
run_exiftool = not options.update
|
||||
if options.update:
|
||||
verbose(f"Writing metadata with exiftool for {pathlib.Path(dest).name}")
|
||||
if not options.dry_run:
|
||||
warning_, error_ = self._write_exif_data(src, options=options)
|
||||
if warning_:
|
||||
exiftool_results.exiftool_warning.append((dest, warning_))
|
||||
if error_:
|
||||
exiftool_results.exiftool_error.append((dest, error_))
|
||||
exiftool_results.error.append((dest, error_))
|
||||
|
||||
exiftool_results.exif_updated.append(dest)
|
||||
exiftool_results.to_touch.append(dest)
|
||||
return exiftool_results
|
||||
|
||||
def _should_run_exiftool(self, dest, options: ExportOptions) -> bool:
|
||||
"""Return True if exiftool should be run to update metadata"""
|
||||
run_exiftool = not options.update and not options.force_update
|
||||
if options.update or options.force_update:
|
||||
files_are_different = False
|
||||
old_data = export_db.get_exifdata_for_file(dest)
|
||||
exif_record = options.export_db.get_file_record(dest)
|
||||
old_data = exif_record.exifdata if exif_record else None
|
||||
if old_data is not None:
|
||||
old_data = json.loads(old_data)[0]
|
||||
current_data = json.loads(self._exiftool_json_sidecar(options=options))[
|
||||
0
|
||||
]
|
||||
current_data = json.loads(self._exiftool_json_sidecar(options=options))
|
||||
current_data = current_data[0]
|
||||
if old_data != current_data:
|
||||
files_are_different = True
|
||||
|
||||
@@ -1352,30 +1333,7 @@ class PhotoExporter:
|
||||
# didn't have old data, assume we need to write it
|
||||
# or files were different
|
||||
run_exiftool = True
|
||||
else:
|
||||
verbose(
|
||||
f"Skipped up to date exiftool metadata for {pathlib.Path(dest).name}"
|
||||
)
|
||||
|
||||
if run_exiftool:
|
||||
verbose(f"Writing metadata with exiftool for {pathlib.Path(dest).name}")
|
||||
if not options.dry_run:
|
||||
warning_, error_ = self._write_exif_data(src, options=options)
|
||||
if warning_:
|
||||
exiftool_results.exiftool_warning.append((dest, warning_))
|
||||
if error_:
|
||||
exiftool_results.exiftool_error.append((dest, error_))
|
||||
exiftool_results.error.append((dest, error_))
|
||||
|
||||
export_db.set_data(
|
||||
dest,
|
||||
uuid=self.photo.uuid,
|
||||
exif_stat=fileutil.file_sig(src),
|
||||
exif_json=self._exiftool_json_sidecar(options=options),
|
||||
)
|
||||
exiftool_results.exif_updated.append(dest)
|
||||
exiftool_results.to_touch.append(dest)
|
||||
return exiftool_results
|
||||
return run_exiftool
|
||||
|
||||
def _write_exif_data(self, filepath: str, options: ExportOptions):
|
||||
"""write exif data to image file at filepath
|
||||
@@ -1550,6 +1508,9 @@ class PhotoExporter:
|
||||
person_list = sorted(list(set(person_list)))
|
||||
exif["XMP:PersonInImage"] = person_list.copy()
|
||||
|
||||
if options.face_regions and self.photo.face_info:
|
||||
exif.update(self._get_mwg_face_regions_exiftool())
|
||||
|
||||
# if self.favorite():
|
||||
# exif["Rating"] = 5
|
||||
|
||||
@@ -1632,6 +1593,42 @@ class PhotoExporter:
|
||||
|
||||
return exif
|
||||
|
||||
def _get_mwg_face_regions_exiftool(self):
|
||||
"""Return a dict with MWG face regions for use by exiftool"""
|
||||
if self.photo.orientation in [5, 6, 7, 8]:
|
||||
w = self.photo.height
|
||||
h = self.photo.width
|
||||
else:
|
||||
w = self.photo.width
|
||||
h = self.photo.height
|
||||
exif = {}
|
||||
exif["XMP:RegionAppliedToDimensionsW"] = w
|
||||
exif["XMP:RegionAppliedToDimensionsH"] = h
|
||||
exif["XMP:RegionAppliedToDimensionsUnit"] = "pixel"
|
||||
exif["XMP:RegionName"] = []
|
||||
exif["XMP:RegionType"] = []
|
||||
exif["XMP:RegionAreaX"] = []
|
||||
exif["XMP:RegionAreaY"] = []
|
||||
exif["XMP:RegionAreaW"] = []
|
||||
exif["XMP:RegionAreaH"] = []
|
||||
exif["XMP:RegionAreaUnit"] = []
|
||||
exif["XMP:RegionPersonDisplayName"] = []
|
||||
# exif["XMP:RegionRectangle"] = []
|
||||
for face in self.photo.face_info:
|
||||
if not face.name:
|
||||
continue
|
||||
area = face.mwg_rs_area
|
||||
exif["XMP:RegionName"].append(face.name)
|
||||
exif["XMP:RegionType"].append("Face")
|
||||
exif["XMP:RegionAreaX"].append(area.x)
|
||||
exif["XMP:RegionAreaY"].append(area.y)
|
||||
exif["XMP:RegionAreaW"].append(area.w)
|
||||
exif["XMP:RegionAreaH"].append(area.h)
|
||||
exif["XMP:RegionAreaUnit"].append("normalized")
|
||||
exif["XMP:RegionPersonDisplayName"].append(face.name)
|
||||
# exif["XMP:RegionRectangle"].append(f"{area.x},{area.y},{area.h},{area.w}")
|
||||
return exif
|
||||
|
||||
def _get_exif_keywords(self):
|
||||
"""returns list of keywords found in the file's exif metadata"""
|
||||
keywords = []
|
||||
|
||||
@@ -588,6 +588,7 @@ class PhotoInfo:
|
||||
@property
|
||||
def ismissing(self):
|
||||
"""returns true if photo is missing from disk (which means it's not been downloaded from iCloud)
|
||||
|
||||
NOTE: the photos.db database uses an asynchrounous write-ahead log so changes in Photos
|
||||
do not immediately get written to disk. In particular, I've noticed that downloading
|
||||
an image from the cloud does not force the database to be updated until something else
|
||||
@@ -1488,7 +1489,8 @@ class PhotoInfo:
|
||||
description_template: string; optional template string that will be rendered for use as photo description
|
||||
render_options: an optional osxphotos.phototemplate.RenderOptions instance with options to pass to template renderer
|
||||
|
||||
Returns: list of photos exported
|
||||
Returns:
|
||||
list of photos exported
|
||||
"""
|
||||
|
||||
exporter = PhotoExporter(self)
|
||||
@@ -1728,7 +1730,11 @@ class PhotoInfo:
|
||||
if isinstance(o, (datetime.date, datetime.datetime)):
|
||||
return o.isoformat()
|
||||
|
||||
return json.dumps(self.asdict(), sort_keys=True, default=default)
|
||||
dict_data = self.asdict()
|
||||
for k, v in dict_data.items():
|
||||
if v and isinstance(v, (list, tuple)) and not isinstance(v[0], dict):
|
||||
dict_data[k] = sorted(v)
|
||||
return json.dumps(dict_data, sort_keys=True, default=default)
|
||||
|
||||
def __eq__(self, other):
|
||||
"""Compare two PhotoInfo objects for equality"""
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import logging
|
||||
|
||||
from .._constants import _DB_TABLE_NAMES, _PHOTOS_4_VERSION
|
||||
from ..utils import _db_is_locked, _debug, _open_sql_file
|
||||
from ..utils import _db_is_locked, _open_sql_file
|
||||
from .photosdb_utils import get_db_version
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import uuid as uuidlib
|
||||
from pprint import pformat
|
||||
|
||||
from .._constants import _PHOTOS_4_VERSION, SEARCH_CATEGORY_LABEL
|
||||
from ..utils import _db_is_locked, _debug, _open_sql_file, normalize_unicode
|
||||
from ..utils import _db_is_locked, _open_sql_file, normalize_unicode
|
||||
|
||||
"""
|
||||
This module should be imported in the class defintion of PhotosDB in photosdb.py
|
||||
@@ -139,17 +139,6 @@ def _process_searchinfo(self):
|
||||
_db_searchinfo_labels[label] = [uuid]
|
||||
_db_searchinfo_labels_normalized[label_norm] = [uuid]
|
||||
|
||||
if _debug():
|
||||
logging.debug(
|
||||
"_db_searchinfo_categories: \n" + pformat(self._db_searchinfo_categories)
|
||||
)
|
||||
logging.debug("_db_searchinfo_uuid: \n" + pformat(self._db_searchinfo_uuid))
|
||||
logging.debug("_db_searchinfo_labels: \n" + pformat(self._db_searchinfo_labels))
|
||||
logging.debug(
|
||||
"_db_searchinfo_labels_normalized: \n"
|
||||
+ pformat(self._db_searchinfo_labels_normalized)
|
||||
)
|
||||
|
||||
conn.close()
|
||||
|
||||
|
||||
|
||||
@@ -2456,7 +2456,6 @@ class PhotosDB:
|
||||
verbose("Processing moments.")
|
||||
self._process_moments()
|
||||
|
||||
# done processing, dump debug data if requested
|
||||
verbose("Done processing details from Photos library.")
|
||||
|
||||
def _process_moments(self):
|
||||
|
||||
@@ -99,7 +99,7 @@ OPERATOR:
|
||||
PathSep:
|
||||
(
|
||||
"("
|
||||
(value=/[^\(\)\{\}]{0,1}/)?
|
||||
(value=/[^\(\)\{\}]+/)?
|
||||
")"
|
||||
)?
|
||||
;
|
||||
|
||||
@@ -211,10 +211,12 @@ class SearchInfo:
|
||||
"""return list of text for a specified category ID"""
|
||||
if self._db_searchinfo:
|
||||
content = "normalized_string" if self._normalized else "content_string"
|
||||
return [
|
||||
rec[content]
|
||||
for rec in self._db_searchinfo
|
||||
if rec["category"] == category
|
||||
]
|
||||
return sorted(
|
||||
[
|
||||
rec[content]
|
||||
for rec in self._db_searchinfo
|
||||
if rec["category"] == category
|
||||
]
|
||||
)
|
||||
else:
|
||||
return []
|
||||
|
||||
@@ -103,6 +103,8 @@
|
||||
% if photo.face_info:
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>${photo.width if photo.orientation in [5, 6, 7, 8] else photo.height}</stDim:h>
|
||||
<stDim:w>${photo.height if photo.orientation in [5, 6, 7, 8] else photo.width}</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -103,6 +103,8 @@
|
||||
% if photo.face_info:
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>${photo.width if photo.orientation in [5, 6, 7, 8] else photo.height}</stDim:h>
|
||||
<stDim:w>${photo.height if photo.orientation in [5, 6, 7, 8] else photo.width}</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -17,14 +17,13 @@ import sys
|
||||
import unicodedata
|
||||
import urllib.parse
|
||||
from plistlib import load as plistload
|
||||
from typing import Callable, List, Optional, Union
|
||||
from typing import Callable, List, Union, Optional
|
||||
|
||||
import CoreFoundation
|
||||
import objc
|
||||
from Foundation import NSFileManager, NSPredicate, NSString
|
||||
|
||||
from ._constants import UNICODE_FORMAT
|
||||
from .path_utils import sanitize_filestem_with_count
|
||||
|
||||
__all__ = [
|
||||
"dd_to_dms_str",
|
||||
@@ -429,10 +428,7 @@ def normalize_unicode(value):
|
||||
|
||||
|
||||
def increment_filename_with_count(
|
||||
filepath: Union[str, pathlib.Path],
|
||||
count: int = 0,
|
||||
lock: bool = False,
|
||||
dry_run: bool = False,
|
||||
filepath: Union[str, pathlib.Path], count: int = 0
|
||||
) -> str:
|
||||
"""Return filename (1).ext, etc if filename.ext exists
|
||||
|
||||
@@ -442,8 +438,6 @@ def increment_filename_with_count(
|
||||
Args:
|
||||
filepath: str or pathlib.Path; full path, including file name
|
||||
count: int; starting increment value
|
||||
lock: bool; if True, create a lock file in form .filename.lock to prevent other processes from using the same filename
|
||||
dry_run: bool; if True, don't actually create lock file
|
||||
|
||||
Returns:
|
||||
tuple of new filepath (or same if not incremented), count
|
||||
@@ -455,32 +449,15 @@ def increment_filename_with_count(
|
||||
dest_files = [f.stem.lower() for f in dest_files]
|
||||
dest_new = f"{dest.stem} ({count})" if count else dest.stem
|
||||
dest_new = normalize_fs_path(dest_new)
|
||||
dest_new = sanitize_filestem_with_count(dest_new, dest.suffix)
|
||||
if lock and not dry_run:
|
||||
dest_lock = "." + dest_new + dest.suffix + ".lock"
|
||||
dest_lock = dest.parent / dest_lock
|
||||
else:
|
||||
dest_lock = pathlib.Path("")
|
||||
|
||||
while dest_new.lower() in dest_files or (
|
||||
lock and not dry_run and dest_lock.exists()
|
||||
):
|
||||
while dest_new.lower() in dest_files:
|
||||
count += 1
|
||||
dest_new = normalize_fs_path(f"{dest.stem} ({count})")
|
||||
dest_new = sanitize_filestem_with_count(dest_new, dest.suffix)
|
||||
if lock:
|
||||
dest_lock = "." + dest_new + dest.suffix + ".lock"
|
||||
dest_lock = dest.parent / dest_lock
|
||||
if lock and not dry_run:
|
||||
dest_lock.touch()
|
||||
dest = dest.parent / f"{dest_new}{dest.suffix}"
|
||||
|
||||
return normalize_fs_path(str(dest)), count
|
||||
|
||||
|
||||
def increment_filename(
|
||||
filepath: Union[str, pathlib.Path], lock: bool = False, dry_run: bool = False
|
||||
) -> str:
|
||||
def increment_filename(filepath: Union[str, pathlib.Path]) -> str:
|
||||
"""Return filename (1).ext, etc if filename.ext exists
|
||||
|
||||
If file exists in filename's parent folder with same stem as filename,
|
||||
@@ -488,17 +465,13 @@ def increment_filename(
|
||||
|
||||
Args:
|
||||
filepath: str or pathlib.Path; full path, including file name
|
||||
lock: bool; if True, creates a lock file in form .filename.lock to prevent other processes from using the same filename
|
||||
dry_run: bool; if True, don't actually create lock file
|
||||
|
||||
Returns:
|
||||
new filepath (or same if not incremented)
|
||||
|
||||
Note: This obviously is subject to race condition so using with caution but using lock=True reduces the risk of race condition (but lock files must be cleaned up)
|
||||
Note: This obviously is subject to race condition so using with caution.
|
||||
"""
|
||||
new_filepath, _ = increment_filename_with_count(
|
||||
filepath, lock=lock, dry_run=dry_run
|
||||
)
|
||||
new_filepath, _ = increment_filename_with_count(filepath)
|
||||
return new_filepath
|
||||
|
||||
|
||||
|
||||
8
setup.py
8
setup.py
@@ -74,11 +74,12 @@ setup(
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
],
|
||||
install_requires=[
|
||||
"Click>=8.0.1,<9.0",
|
||||
"Mako>=1.1.4,<1.2.0",
|
||||
"PyYAML>=5.4.1,<5.5.0",
|
||||
"bitmath>=1.3.3.1,<1.4.0.0",
|
||||
"bpylist2==3.0.2",
|
||||
"Click>=8.0.1,<9.0",
|
||||
"dataclasses==0.7;python_version<'3.7'",
|
||||
"Mako>=1.1.4,<1.2.0",
|
||||
"more-itertools>=8.8.0,<9.0.0",
|
||||
"objexplore>=1.5.5,<1.6.0",
|
||||
"osxmetadata>=0.99.34,<1.0.0",
|
||||
@@ -86,16 +87,15 @@ setup(
|
||||
"photoscript>=0.1.4,<0.2.0",
|
||||
"ptpython>=3.0.20,<4.0.0",
|
||||
"pyobjc-core>=7.3,<9.0",
|
||||
"pyobjc-framework-AVFoundation>=7.3,<9.0",
|
||||
"pyobjc-framework-AppleScriptKit>=7.3,<9.0",
|
||||
"pyobjc-framework-AppleScriptObjC>=7.3,<9.0",
|
||||
"pyobjc-framework-AVFoundation>=7.3,<9.0",
|
||||
"pyobjc-framework-Cocoa>=7.3,<9.0",
|
||||
"pyobjc-framework-CoreServices>=7.2,<9.0",
|
||||
"pyobjc-framework-Metal>=7.3,<9.0",
|
||||
"pyobjc-framework-Photos>=7.3,<9.0",
|
||||
"pyobjc-framework-Quartz>=7.3,<9.0",
|
||||
"pyobjc-framework-Vision>=7.3,<9.0",
|
||||
"PyYAML>=5.4.1,<5.5.0",
|
||||
"rich>=10.6.0,<=11.0.0",
|
||||
"textx>=2.3.0,<3.0.0",
|
||||
"toml>=0.10.2,<0.11.0",
|
||||
|
||||
@@ -40,7 +40,7 @@ else:
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def reset_singletons():
|
||||
""" Need to clean up any ExifTool singletons between tests """
|
||||
"""Need to clean up any ExifTool singletons between tests"""
|
||||
_ExifToolProc.instance = None
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ def pytest_collection_modifyitems(config, items):
|
||||
|
||||
|
||||
def copy_photos_library(photos_library=TEST_LIBRARY, delay=0):
|
||||
""" copy the test library and open Photos, returns path to copied library """
|
||||
"""copy the test library and open Photos, returns path to copied library"""
|
||||
script = AppleScript(
|
||||
"""
|
||||
tell application "Photos"
|
||||
@@ -118,3 +118,9 @@ def copy_photos_library(photos_library=TEST_LIBRARY, delay=0):
|
||||
@pytest.fixture
|
||||
def addalbum_library():
|
||||
copy_photos_library(delay=10)
|
||||
|
||||
|
||||
def copy_photos_library_to_path(photos_library_path: str, dest_path: str) -> str:
|
||||
"""Copy a photos library to a folder"""
|
||||
ditto(photos_library_path, dest_path)
|
||||
return dest_path
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import pathlib
|
||||
|
||||
import osxphotos
|
||||
from osxphotos.photoexporter import PhotoExporter, ExportOptions
|
||||
|
||||
PHOTOS_DB_15_7 = "./tests/Test-10.15.7.photoslibrary/database/photos.db"
|
||||
PHOTOS_DB_14_6 = "./tests/Test-10.14.6.photoslibrary/database/photos.db"
|
||||
@@ -31,7 +32,7 @@ SIDECAR_DIR = "tests/sidecars"
|
||||
|
||||
|
||||
def generate_sidecars(dbname, uuid_dict):
|
||||
""" generate XMP and JSON sidecars for testing """
|
||||
"""generate XMP and JSON sidecars for testing"""
|
||||
photosdb = osxphotos.PhotosDB(dbname)
|
||||
|
||||
for _, uuid in uuid_dict.items():
|
||||
@@ -39,7 +40,8 @@ def generate_sidecars(dbname, uuid_dict):
|
||||
|
||||
# plain xmp
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}.xmp")
|
||||
xmp = photo._xmp_sidecar()
|
||||
exporter = PhotoExporter(photo)
|
||||
xmp = exporter._xmp_sidecar()
|
||||
with open(sidecar, "w") as file:
|
||||
file.write(xmp)
|
||||
|
||||
@@ -47,63 +49,76 @@ def generate_sidecars(dbname, uuid_dict):
|
||||
ext = osxphotos.uti.get_preferred_uti_extension(photo.uti)
|
||||
ext = "jpg" if ext == "jpeg" else ext
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_ext.xmp")
|
||||
xmp = photo._xmp_sidecar(extension=ext)
|
||||
xmp = exporter._xmp_sidecar(extension=ext)
|
||||
with open(sidecar, "w") as file:
|
||||
file.write(xmp)
|
||||
|
||||
# persons_as_keywords
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_persons_as_keywords.xmp")
|
||||
xmp = photo._xmp_sidecar(use_persons_as_keywords=True, extension=ext)
|
||||
xmp = exporter._xmp_sidecar(
|
||||
ExportOptions(use_persons_as_keywords=True), extension=ext
|
||||
)
|
||||
with open(sidecar, "w") as file:
|
||||
file.write(xmp)
|
||||
|
||||
# albums_as_keywords
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_albums_as_keywords.xmp")
|
||||
xmp = photo._xmp_sidecar(use_albums_as_keywords=True, extension=ext)
|
||||
xmp = exporter._xmp_sidecar(
|
||||
ExportOptions(use_albums_as_keywords=True), extension=ext
|
||||
)
|
||||
with open(sidecar, "w") as file:
|
||||
file.write(xmp)
|
||||
|
||||
# keyword_template
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_keyword_template.xmp")
|
||||
xmp = photo._xmp_sidecar(
|
||||
keyword_template=["{created.year}", "{folder_album}"], extension=ext
|
||||
xmp = exporter._xmp_sidecar(
|
||||
ExportOptions(keyword_template=["{created.year}", "{folder_album}"]),
|
||||
extension=ext,
|
||||
)
|
||||
with open(sidecar, "w") as file:
|
||||
file.write(xmp)
|
||||
|
||||
# generate JSON files
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}.json")
|
||||
json_ = photo._exiftool_json_sidecar()
|
||||
json_ = exporter._exiftool_json_sidecar()
|
||||
with open(sidecar, "w") as file:
|
||||
file.write(json_)
|
||||
|
||||
# no tag groups
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_no_tag_groups.json")
|
||||
json_ = photo._exiftool_json_sidecar(tag_groups=False)
|
||||
json_ = exporter._exiftool_json_sidecar(tag_groups=False)
|
||||
with open(sidecar, "w") as file:
|
||||
file.write(json_)
|
||||
|
||||
# ignore_date_modified
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_ignore_date_modified.json")
|
||||
json_ = photo._exiftool_json_sidecar(ignore_date_modified=True)
|
||||
json_ = exporter._exiftool_json_sidecar(
|
||||
ExportOptions(ignore_date_modified=True)
|
||||
)
|
||||
with open(sidecar, "w") as file:
|
||||
file.write(json_)
|
||||
|
||||
# keyword_template
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_keyword_template.json")
|
||||
json_ = photo._exiftool_json_sidecar(keyword_template=["{folder_album}"])
|
||||
json_ = exporter._exiftool_json_sidecar(
|
||||
ExportOptions(keyword_template=["{folder_album}"])
|
||||
)
|
||||
with open(sidecar, "w") as file:
|
||||
file.write(json_)
|
||||
|
||||
# persons_as_keywords
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_persons_as_keywords.json")
|
||||
json_ = photo._exiftool_json_sidecar(use_persons_as_keywords=True)
|
||||
json_ = exporter._exiftool_json_sidecar(
|
||||
ExportOptions(use_persons_as_keywords=True)
|
||||
)
|
||||
with open(sidecar, "w") as file:
|
||||
file.write(json_)
|
||||
|
||||
# albums_as_keywords
|
||||
sidecar = str(pathlib.Path(SIDECAR_DIR) / f"{uuid}_albums_as_keywords.json")
|
||||
json_ = photo._exiftool_json_sidecar(use_albums_as_keywords=True)
|
||||
json_ = exporter._exiftool_json_sidecar(
|
||||
ExportOptions(use_albums_as_keywords=True)
|
||||
)
|
||||
with open(sidecar, "w") as file:
|
||||
file.write(json_)
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie"], "XMP:RegionAppliedToDimensionsW": 1365, "XMP:RegionAppliedToDimensionsH": 2048, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Katie"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.5832663178443909], "XMP:RegionAreaY": [0.27730926126241684], "XMP:RegionAreaW": [0.24365156888961792], "XMP:RegionAreaH": [0.16239472242887132], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
@@ -52,6 +52,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>2048</stDim:h>
|
||||
<stDim:w>1365</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:Subject": ["AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:TagsList": ["AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:PersonInImage": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:Subject": ["AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:TagsList": ["AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:PersonInImage": ["Katie"], "XMP:RegionAppliedToDimensionsW": 1365, "XMP:RegionAppliedToDimensionsH": 2048, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Katie"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.5832663178443909], "XMP:RegionAreaY": [0.27730926126241684], "XMP:RegionAreaW": [0.24365156888961792], "XMP:RegionAreaH": [0.16239472242887132], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
@@ -58,6 +58,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>2048</stDim:h>
|
||||
<stDim:w>1365</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>2048</stDim:h>
|
||||
<stDim:w>1365</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie"], "XMP:RegionAppliedToDimensionsW": 1365, "XMP:RegionAppliedToDimensionsH": 2048, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Katie"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.5832663178443909], "XMP:RegionAreaY": [0.27730926126241684], "XMP:RegionAreaW": [0.24365156888961792], "XMP:RegionAreaH": [0.16239472242887132], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Folder1/SubFolder2/AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:Subject": ["Folder1/SubFolder2/AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:TagsList": ["Folder1/SubFolder2/AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:PersonInImage": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Folder1/SubFolder2/AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:Subject": ["Folder1/SubFolder2/AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:TagsList": ["Folder1/SubFolder2/AlbumInFolder", "Kids", "Pumpkin Farm", "Test Album (1)"], "XMP:PersonInImage": ["Katie"], "XMP:RegionAppliedToDimensionsW": 1365, "XMP:RegionAppliedToDimensionsH": 2048, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Katie"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.5832663178443909], "XMP:RegionAreaY": [0.27730926126241684], "XMP:RegionAreaW": [0.24365156888961792], "XMP:RegionAreaH": [0.16239472242887132], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
@@ -60,6 +60,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>2048</stDim:h>
|
||||
<stDim:w>1365</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"ImageDescription": "Girl holding pumpkin", "Description": "Girl holding pumpkin", "Caption-Abstract": "Girl holding pumpkin", "Title": "I found one!", "ObjectName": "I found one!", "Keywords": ["Kids"], "Subject": ["Kids"], "TagsList": ["Kids"], "PersonInImage": ["Katie"], "DateTimeOriginal": "2018:09:28 16:07:07", "CreateDate": "2018:09:28 16:07:07", "OffsetTimeOriginal": "-04:00", "DateCreated": "2018:09:28", "TimeCreated": "16:07:07-04:00", "ModifyDate": "2018:09:28 16:07:07"}]
|
||||
[{"ImageDescription": "Girl holding pumpkin", "Description": "Girl holding pumpkin", "Caption-Abstract": "Girl holding pumpkin", "Title": "I found one!", "ObjectName": "I found one!", "Keywords": ["Kids"], "Subject": ["Kids"], "TagsList": ["Kids"], "PersonInImage": ["Katie"], "RegionAppliedToDimensionsW": 1365, "RegionAppliedToDimensionsH": 2048, "RegionAppliedToDimensionsUnit": "pixel", "RegionName": ["Katie"], "RegionType": ["Face"], "RegionAreaX": [0.5832663178443909], "RegionAreaY": [0.27730926126241684], "RegionAreaW": [0.24365156888961792], "RegionAreaH": [0.16239472242887132], "RegionAreaUnit": ["normalized"], "RegionPersonDisplayName": ["Katie"], "DateTimeOriginal": "2018:09:28 16:07:07", "CreateDate": "2018:09:28 16:07:07", "OffsetTimeOriginal": "-04:00", "DateCreated": "2018:09:28", "TimeCreated": "16:07:07-04:00", "ModifyDate": "2018:09:28 16:07:07"}]
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Katie", "Kids"], "XMP:Subject": ["Katie", "Kids"], "XMP:TagsList": ["Katie", "Kids"], "XMP:PersonInImage": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Katie", "Kids"], "XMP:Subject": ["Katie", "Kids"], "XMP:TagsList": ["Katie", "Kids"], "XMP:PersonInImage": ["Katie"], "XMP:RegionAppliedToDimensionsW": 1365, "XMP:RegionAppliedToDimensionsH": 2048, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Katie"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.5832663178443909], "XMP:RegionAreaY": [0.27730926126241684], "XMP:RegionAreaW": [0.24365156888961792], "XMP:RegionAreaH": [0.16239472242887132], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Katie"], "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
@@ -54,6 +54,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>2048</stDim:h>
|
||||
<stDim:w>1365</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["wedding"], "XMP:Subject": ["wedding"], "XMP:TagsList": ["wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:11:27 01:30:16"}]
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["wedding"], "XMP:Subject": ["wedding"], "XMP:TagsList": ["wedding"], "XMP:PersonInImage": ["Maria"], "XMP:RegionAppliedToDimensionsW": 1526, "XMP:RegionAppliedToDimensionsH": 1325, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Maria"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.40229974687099457], "XMP:RegionAreaY": [0.41379398107528687], "XMP:RegionAreaW": [0.3420099108278517], "XMP:RegionAreaH": [0.39389216899871826], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:11:27 01:30:16"}]
|
||||
@@ -52,6 +52,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1325</stDim:h>
|
||||
<stDim:w>1526</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["wedding"], "XMP:Subject": ["wedding"], "XMP:TagsList": ["wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:11:27 01:30:16"}]
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["wedding"], "XMP:Subject": ["wedding"], "XMP:TagsList": ["wedding"], "XMP:PersonInImage": ["Maria"], "XMP:RegionAppliedToDimensionsW": 1526, "XMP:RegionAppliedToDimensionsH": 1325, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Maria"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.40229974687099457], "XMP:RegionAreaY": [0.41379398107528687], "XMP:RegionAreaW": [0.3420099108278517], "XMP:RegionAreaH": [0.39389216899871826], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:11:27 01:30:16"}]
|
||||
@@ -52,6 +52,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1325</stDim:h>
|
||||
<stDim:w>1526</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1325</stDim:h>
|
||||
<stDim:w>1526</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["wedding"], "XMP:Subject": ["wedding"], "XMP:TagsList": ["wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:04:15 14:40:24"}]
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["wedding"], "XMP:Subject": ["wedding"], "XMP:TagsList": ["wedding"], "XMP:PersonInImage": ["Maria"], "XMP:RegionAppliedToDimensionsW": 1526, "XMP:RegionAppliedToDimensionsH": 1325, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Maria"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.40229974687099457], "XMP:RegionAreaY": [0.41379398107528687], "XMP:RegionAreaW": [0.3420099108278517], "XMP:RegionAreaH": [0.39389216899871826], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:04:15 14:40:24"}]
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["wedding"], "XMP:Subject": ["wedding"], "XMP:TagsList": ["wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:11:27 01:30:16"}]
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["wedding"], "XMP:Subject": ["wedding"], "XMP:TagsList": ["wedding"], "XMP:PersonInImage": ["Maria"], "XMP:RegionAppliedToDimensionsW": 1526, "XMP:RegionAppliedToDimensionsH": 1325, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Maria"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.40229974687099457], "XMP:RegionAreaY": [0.41379398107528687], "XMP:RegionAreaW": [0.3420099108278517], "XMP:RegionAreaH": [0.39389216899871826], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:11:27 01:30:16"}]
|
||||
@@ -54,6 +54,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1325</stDim:h>
|
||||
<stDim:w>1526</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"ImageDescription": "Bride Wedding day", "Description": "Bride Wedding day", "Caption-Abstract": "Bride Wedding day", "Keywords": ["wedding"], "Subject": ["wedding"], "TagsList": ["wedding"], "PersonInImage": ["Maria"], "DateTimeOriginal": "2019:04:15 14:40:24", "CreateDate": "2019:04:15 14:40:24", "OffsetTimeOriginal": "-04:00", "DateCreated": "2019:04:15", "TimeCreated": "14:40:24-04:00", "ModifyDate": "2019:11:27 01:30:16"}]
|
||||
[{"ImageDescription": "Bride Wedding day", "Description": "Bride Wedding day", "Caption-Abstract": "Bride Wedding day", "Keywords": ["wedding"], "Subject": ["wedding"], "TagsList": ["wedding"], "PersonInImage": ["Maria"], "RegionAppliedToDimensionsW": 1526, "RegionAppliedToDimensionsH": 1325, "RegionAppliedToDimensionsUnit": "pixel", "RegionName": ["Maria"], "RegionType": ["Face"], "RegionAreaX": [0.40229974687099457], "RegionAreaY": [0.41379398107528687], "RegionAreaW": [0.3420099108278517], "RegionAreaH": [0.39389216899871826], "RegionAreaUnit": ["normalized"], "RegionPersonDisplayName": ["Maria"], "DateTimeOriginal": "2019:04:15 14:40:24", "CreateDate": "2019:04:15 14:40:24", "OffsetTimeOriginal": "-04:00", "DateCreated": "2019:04:15", "TimeCreated": "14:40:24-04:00", "ModifyDate": "2019:11:27 01:30:16"}]
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["Maria", "wedding"], "XMP:Subject": ["Maria", "wedding"], "XMP:TagsList": ["Maria", "wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:11:27 01:30:16"}]
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["Maria", "wedding"], "XMP:Subject": ["Maria", "wedding"], "XMP:TagsList": ["Maria", "wedding"], "XMP:PersonInImage": ["Maria"], "XMP:RegionAppliedToDimensionsW": 1526, "XMP:RegionAppliedToDimensionsH": 1325, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Maria"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.40229974687099457], "XMP:RegionAreaY": [0.41379398107528687], "XMP:RegionAreaW": [0.3420099108278517], "XMP:RegionAreaH": [0.39389216899871826], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:11:27 01:30:16"}]
|
||||
@@ -54,6 +54,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1325</stDim:h>
|
||||
<stDim:w>1526</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "IPTC:Caption-Abstract": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:ObjectName": "Can we carry this?", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie", "Suzy"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]
|
||||
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "IPTC:Caption-Abstract": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:ObjectName": "Can we carry this?", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie", "Suzy"], "XMP:RegionAppliedToDimensionsW": 2048, "XMP:RegionAppliedToDimensionsH": 1365, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Suzy", "Katie"], "XMP:RegionType": ["Face", "Face"], "XMP:RegionAreaX": [0.3097837567329407, 0.7126731872558595], "XMP:RegionAreaY": [0.33553561195731163, 0.4239872685185184], "XMP:RegionAreaW": [0.07461518356649322, 0.05], "XMP:RegionAreaH": [0.1119501069188118, 0.07501831501831502], "XMP:RegionAreaUnit": ["normalized", "normalized"], "XMP:RegionPersonDisplayName": ["Suzy", "Katie"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]
|
||||
@@ -53,6 +53,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1365</stDim:h>
|
||||
<stDim:w>2048</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "IPTC:Caption-Abstract": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:ObjectName": "Can we carry this?", "IPTC:Keywords": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:Subject": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:TagsList": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:PersonInImage": ["Katie", "Suzy"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]
|
||||
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "IPTC:Caption-Abstract": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:ObjectName": "Can we carry this?", "IPTC:Keywords": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:Subject": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:TagsList": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:PersonInImage": ["Katie", "Suzy"], "XMP:RegionAppliedToDimensionsW": 2048, "XMP:RegionAppliedToDimensionsH": 1365, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Suzy", "Katie"], "XMP:RegionType": ["Face", "Face"], "XMP:RegionAreaX": [0.3097837567329407, 0.7126731872558595], "XMP:RegionAreaY": [0.33553561195731163, 0.4239872685185184], "XMP:RegionAreaW": [0.07461518356649322, 0.05], "XMP:RegionAreaH": [0.1119501069188118, 0.07501831501831502], "XMP:RegionAreaUnit": ["normalized", "normalized"], "XMP:RegionPersonDisplayName": ["Suzy", "Katie"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]
|
||||
@@ -57,6 +57,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1365</stDim:h>
|
||||
<stDim:w>2048</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -53,6 +53,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1365</stDim:h>
|
||||
<stDim:w>2048</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "IPTC:Caption-Abstract": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:ObjectName": "Can we carry this?", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie", "Suzy"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]
|
||||
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "IPTC:Caption-Abstract": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:ObjectName": "Can we carry this?", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie", "Suzy"], "XMP:RegionAppliedToDimensionsW": 2048, "XMP:RegionAppliedToDimensionsH": 1365, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Suzy", "Katie"], "XMP:RegionType": ["Face", "Face"], "XMP:RegionAreaX": [0.3097837567329407, 0.7126731872558595], "XMP:RegionAreaY": [0.33553561195731163, 0.4239872685185184], "XMP:RegionAreaW": [0.07461518356649322, 0.05], "XMP:RegionAreaH": [0.1119501069188118, 0.07501831501831502], "XMP:RegionAreaUnit": ["normalized", "normalized"], "XMP:RegionPersonDisplayName": ["Suzy", "Katie"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "IPTC:Caption-Abstract": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:ObjectName": "Can we carry this?", "IPTC:Keywords": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:Subject": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:TagsList": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:PersonInImage": ["Katie", "Suzy"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]
|
||||
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "IPTC:Caption-Abstract": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:ObjectName": "Can we carry this?", "IPTC:Keywords": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:Subject": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:TagsList": ["Kids", "Pumpkin Farm", "Test Album"], "XMP:PersonInImage": ["Katie", "Suzy"], "XMP:RegionAppliedToDimensionsW": 2048, "XMP:RegionAppliedToDimensionsH": 1365, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Suzy", "Katie"], "XMP:RegionType": ["Face", "Face"], "XMP:RegionAreaX": [0.3097837567329407, 0.7126731872558595], "XMP:RegionAreaY": [0.33553561195731163, 0.4239872685185184], "XMP:RegionAreaW": [0.07461518356649322, 0.05], "XMP:RegionAreaH": [0.1119501069188118, 0.07501831501831502], "XMP:RegionAreaUnit": ["normalized", "normalized"], "XMP:RegionPersonDisplayName": ["Suzy", "Katie"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]
|
||||
@@ -59,6 +59,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1365</stDim:h>
|
||||
<stDim:w>2048</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"ImageDescription": "Girls with pumpkins", "Description": "Girls with pumpkins", "Caption-Abstract": "Girls with pumpkins", "Title": "Can we carry this?", "ObjectName": "Can we carry this?", "Keywords": ["Kids"], "Subject": ["Kids"], "TagsList": ["Kids"], "PersonInImage": ["Katie", "Suzy"], "DateTimeOriginal": "2018:09:28 15:35:49", "CreateDate": "2018:09:28 15:35:49", "OffsetTimeOriginal": "-04:00", "DateCreated": "2018:09:28", "TimeCreated": "15:35:49-04:00", "ModifyDate": "2018:09:28 15:35:49"}]
|
||||
[{"ImageDescription": "Girls with pumpkins", "Description": "Girls with pumpkins", "Caption-Abstract": "Girls with pumpkins", "Title": "Can we carry this?", "ObjectName": "Can we carry this?", "Keywords": ["Kids"], "Subject": ["Kids"], "TagsList": ["Kids"], "PersonInImage": ["Katie", "Suzy"], "RegionAppliedToDimensionsW": 2048, "RegionAppliedToDimensionsH": 1365, "RegionAppliedToDimensionsUnit": "pixel", "RegionName": ["Suzy", "Katie"], "RegionType": ["Face", "Face"], "RegionAreaX": [0.3097837567329407, 0.7126731872558595], "RegionAreaY": [0.33553561195731163, 0.4239872685185184], "RegionAreaW": [0.07461518356649322, 0.05], "RegionAreaH": [0.1119501069188118, 0.07501831501831502], "RegionAreaUnit": ["normalized", "normalized"], "RegionPersonDisplayName": ["Suzy", "Katie"], "DateTimeOriginal": "2018:09:28 15:35:49", "CreateDate": "2018:09:28 15:35:49", "OffsetTimeOriginal": "-04:00", "DateCreated": "2018:09:28", "TimeCreated": "15:35:49-04:00", "ModifyDate": "2018:09:28 15:35:49"}]
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "IPTC:Caption-Abstract": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:ObjectName": "Can we carry this?", "IPTC:Keywords": ["Katie", "Kids", "Suzy"], "XMP:Subject": ["Katie", "Kids", "Suzy"], "XMP:TagsList": ["Katie", "Kids", "Suzy"], "XMP:PersonInImage": ["Katie", "Suzy"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]
|
||||
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "IPTC:Caption-Abstract": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:ObjectName": "Can we carry this?", "IPTC:Keywords": ["Katie", "Kids", "Suzy"], "XMP:Subject": ["Katie", "Kids", "Suzy"], "XMP:TagsList": ["Katie", "Kids", "Suzy"], "XMP:PersonInImage": ["Katie", "Suzy"], "XMP:RegionAppliedToDimensionsW": 2048, "XMP:RegionAppliedToDimensionsH": 1365, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Suzy", "Katie"], "XMP:RegionType": ["Face", "Face"], "XMP:RegionAreaX": [0.3097837567329407, 0.7126731872558595], "XMP:RegionAreaY": [0.33553561195731163, 0.4239872685185184], "XMP:RegionAreaW": [0.07461518356649322, 0.05], "XMP:RegionAreaH": [0.1119501069188118, 0.07501831501831502], "XMP:RegionAreaUnit": ["normalized", "normalized"], "XMP:RegionPersonDisplayName": ["Suzy", "Katie"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]
|
||||
@@ -57,6 +57,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1365</stDim:h>
|
||||
<stDim:w>2048</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie"], "EXIF:GPSLatitude": 41.256566, "EXIF:GPSLongitude": -95.940257, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie"], "XMP:RegionAppliedToDimensionsW": 1365, "XMP:RegionAppliedToDimensionsH": 2048, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Katie"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.5898191407322884], "XMP:RegionAreaY": [0.28164292871952057], "XMP:RegionAreaW": [0.22411711513996124], "XMP:RegionAreaH": [0.14937493269826518], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Katie"], "EXIF:GPSLatitude": 41.256566, "EXIF:GPSLongitude": -95.940257, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
@@ -54,6 +54,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>2048</stDim:h>
|
||||
<stDim:w>1365</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Kids", "Multi Keyword", "Pumpkin Farm", "Test Album"], "XMP:Subject": ["Kids", "Multi Keyword", "Pumpkin Farm", "Test Album"], "XMP:TagsList": ["Kids", "Multi Keyword", "Pumpkin Farm", "Test Album"], "XMP:PersonInImage": ["Katie"], "EXIF:GPSLatitude": 41.256566, "EXIF:GPSLongitude": -95.940257, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Kids", "Multi Keyword", "Pumpkin Farm", "Test Album"], "XMP:Subject": ["Kids", "Multi Keyword", "Pumpkin Farm", "Test Album"], "XMP:TagsList": ["Kids", "Multi Keyword", "Pumpkin Farm", "Test Album"], "XMP:PersonInImage": ["Katie"], "XMP:RegionAppliedToDimensionsW": 1365, "XMP:RegionAppliedToDimensionsH": 2048, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Katie"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.5898191407322884], "XMP:RegionAreaY": [0.28164292871952057], "XMP:RegionAreaW": [0.22411711513996124], "XMP:RegionAreaH": [0.14937493269826518], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Katie"], "EXIF:GPSLatitude": 41.256566, "EXIF:GPSLongitude": -95.940257, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
@@ -60,6 +60,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>2048</stDim:h>
|
||||
<stDim:w>1365</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -54,6 +54,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>2048</stDim:h>
|
||||
<stDim:w>1365</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie"], "EXIF:GPSLatitude": 41.256566, "EXIF:GPSLongitude": -95.940257, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie"], "XMP:RegionAppliedToDimensionsW": 1365, "XMP:RegionAppliedToDimensionsH": 2048, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Katie"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.5898191407322884], "XMP:RegionAreaY": [0.28164292871952057], "XMP:RegionAreaW": [0.22411711513996124], "XMP:RegionAreaH": [0.14937493269826518], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Katie"], "EXIF:GPSLatitude": 41.256566, "EXIF:GPSLongitude": -95.940257, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Kids", "Multi Keyword", "Pumpkin Farm", "Test Album"], "XMP:Subject": ["Kids", "Multi Keyword", "Pumpkin Farm", "Test Album"], "XMP:TagsList": ["Kids", "Multi Keyword", "Pumpkin Farm", "Test Album"], "XMP:PersonInImage": ["Katie"], "EXIF:GPSLatitude": 41.256566, "EXIF:GPSLongitude": -95.940257, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Kids", "Multi Keyword", "Pumpkin Farm", "Test Album"], "XMP:Subject": ["Kids", "Multi Keyword", "Pumpkin Farm", "Test Album"], "XMP:TagsList": ["Kids", "Multi Keyword", "Pumpkin Farm", "Test Album"], "XMP:PersonInImage": ["Katie"], "XMP:RegionAppliedToDimensionsW": 1365, "XMP:RegionAppliedToDimensionsH": 2048, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Katie"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.5898191407322884], "XMP:RegionAreaY": [0.28164292871952057], "XMP:RegionAreaW": [0.22411711513996124], "XMP:RegionAreaH": [0.14937493269826518], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Katie"], "EXIF:GPSLatitude": 41.256566, "EXIF:GPSLongitude": -95.940257, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
@@ -62,6 +62,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>2048</stDim:h>
|
||||
<stDim:w>1365</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"ImageDescription": "Girl holding pumpkin", "Description": "Girl holding pumpkin", "Caption-Abstract": "Girl holding pumpkin", "Title": "I found one!", "ObjectName": "I found one!", "Keywords": ["Kids"], "Subject": ["Kids"], "TagsList": ["Kids"], "PersonInImage": ["Katie"], "GPSLatitude": 41.256566, "GPSLongitude": -95.940257, "GPSLatitudeRef": "N", "GPSLongitudeRef": "W", "DateTimeOriginal": "2018:09:28 16:07:07", "CreateDate": "2018:09:28 16:07:07", "OffsetTimeOriginal": "-04:00", "DateCreated": "2018:09:28", "TimeCreated": "16:07:07-04:00", "ModifyDate": "2018:09:28 16:07:07"}]
|
||||
[{"ImageDescription": "Girl holding pumpkin", "Description": "Girl holding pumpkin", "Caption-Abstract": "Girl holding pumpkin", "Title": "I found one!", "ObjectName": "I found one!", "Keywords": ["Kids"], "Subject": ["Kids"], "TagsList": ["Kids"], "PersonInImage": ["Katie"], "RegionAppliedToDimensionsW": 1365, "RegionAppliedToDimensionsH": 2048, "RegionAppliedToDimensionsUnit": "pixel", "RegionName": ["Katie"], "RegionType": ["Face"], "RegionAreaX": [0.5898191407322884], "RegionAreaY": [0.28164292871952057], "RegionAreaW": [0.22411711513996124], "RegionAreaH": [0.14937493269826518], "RegionAreaUnit": ["normalized"], "RegionPersonDisplayName": ["Katie"], "GPSLatitude": 41.256566, "GPSLongitude": -95.940257, "GPSLatitudeRef": "N", "GPSLongitudeRef": "W", "DateTimeOriginal": "2018:09:28 16:07:07", "CreateDate": "2018:09:28 16:07:07", "OffsetTimeOriginal": "-04:00", "DateCreated": "2018:09:28", "TimeCreated": "16:07:07-04:00", "ModifyDate": "2018:09:28 16:07:07"}]
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Katie", "Kids"], "XMP:Subject": ["Katie", "Kids"], "XMP:TagsList": ["Katie", "Kids"], "XMP:PersonInImage": ["Katie"], "EXIF:GPSLatitude": 41.256566, "EXIF:GPSLongitude": -95.940257, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
[{"EXIF:ImageDescription": "Girl holding pumpkin", "XMP:Description": "Girl holding pumpkin", "IPTC:Caption-Abstract": "Girl holding pumpkin", "XMP:Title": "I found one!", "IPTC:ObjectName": "I found one!", "IPTC:Keywords": ["Katie", "Kids"], "XMP:Subject": ["Katie", "Kids"], "XMP:TagsList": ["Katie", "Kids"], "XMP:PersonInImage": ["Katie"], "XMP:RegionAppliedToDimensionsW": 1365, "XMP:RegionAppliedToDimensionsH": 2048, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Katie"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.5898191407322884], "XMP:RegionAreaY": [0.28164292871952057], "XMP:RegionAreaW": [0.22411711513996124], "XMP:RegionAreaH": [0.14937493269826518], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Katie"], "EXIF:GPSLatitude": 41.256566, "EXIF:GPSLongitude": -95.940257, "EXIF:GPSLatitudeRef": "N", "EXIF:GPSLongitudeRef": "W", "EXIF:DateTimeOriginal": "2018:09:28 16:07:07", "EXIF:CreateDate": "2018:09:28 16:07:07", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "16:07:07-04:00", "EXIF:ModifyDate": "2018:09:28 16:07:07"}]
|
||||
@@ -56,6 +56,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>2048</stDim:h>
|
||||
<stDim:w>1365</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["Maria", "wedding"], "XMP:Subject": ["Maria", "wedding"], "XMP:TagsList": ["Maria", "wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:07:27 17:33:28"}]
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["Maria", "wedding"], "XMP:Subject": ["Maria", "wedding"], "XMP:TagsList": ["Maria", "wedding"], "XMP:PersonInImage": ["Maria"], "XMP:RegionAppliedToDimensionsW": 1526, "XMP:RegionAppliedToDimensionsH": 1325, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Maria"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.41222959756851196], "XMP:RegionAreaY": [0.4221687614917755], "XMP:RegionAreaW": [0.3333342373371124], "XMP:RegionAreaH": [0.3839004122086291], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:07:27 17:33:28"}]
|
||||
@@ -54,6 +54,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1325</stDim:h>
|
||||
<stDim:w>1526</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["AlbumInFolder", "I have a deleted twin", "Maria", "Multi Keyword", "wedding"], "XMP:Subject": ["AlbumInFolder", "I have a deleted twin", "Maria", "Multi Keyword", "wedding"], "XMP:TagsList": ["AlbumInFolder", "I have a deleted twin", "Maria", "Multi Keyword", "wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:07:27 17:33:28"}]
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["AlbumInFolder", "I have a deleted twin", "Maria", "Multi Keyword", "wedding"], "XMP:Subject": ["AlbumInFolder", "I have a deleted twin", "Maria", "Multi Keyword", "wedding"], "XMP:TagsList": ["AlbumInFolder", "I have a deleted twin", "Maria", "Multi Keyword", "wedding"], "XMP:PersonInImage": ["Maria"], "XMP:RegionAppliedToDimensionsW": 1526, "XMP:RegionAppliedToDimensionsH": 1325, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Maria"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.41222959756851196], "XMP:RegionAreaY": [0.4221687614917755], "XMP:RegionAreaW": [0.3333342373371124], "XMP:RegionAreaH": [0.3839004122086291], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:07:27 17:33:28"}]
|
||||
@@ -60,6 +60,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1325</stDim:h>
|
||||
<stDim:w>1526</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -54,6 +54,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1325</stDim:h>
|
||||
<stDim:w>1526</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["Maria", "wedding"], "XMP:Subject": ["Maria", "wedding"], "XMP:TagsList": ["Maria", "wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:04:15 14:40:24"}]
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["Maria", "wedding"], "XMP:Subject": ["Maria", "wedding"], "XMP:TagsList": ["Maria", "wedding"], "XMP:PersonInImage": ["Maria"], "XMP:RegionAppliedToDimensionsW": 1526, "XMP:RegionAppliedToDimensionsH": 1325, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Maria"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.41222959756851196], "XMP:RegionAreaY": [0.4221687614917755], "XMP:RegionAreaW": [0.3333342373371124], "XMP:RegionAreaH": [0.3839004122086291], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:04:15 14:40:24"}]
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["Folder1/SubFolder2/AlbumInFolder", "I have a deleted twin", "Maria", "Multi Keyword", "wedding"], "XMP:Subject": ["Folder1/SubFolder2/AlbumInFolder", "I have a deleted twin", "Maria", "Multi Keyword", "wedding"], "XMP:TagsList": ["Folder1/SubFolder2/AlbumInFolder", "I have a deleted twin", "Maria", "Multi Keyword", "wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:07:27 17:33:28"}]
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["Folder1/SubFolder2/AlbumInFolder", "I have a deleted twin", "Maria", "Multi Keyword", "wedding"], "XMP:Subject": ["Folder1/SubFolder2/AlbumInFolder", "I have a deleted twin", "Maria", "Multi Keyword", "wedding"], "XMP:TagsList": ["Folder1/SubFolder2/AlbumInFolder", "I have a deleted twin", "Maria", "Multi Keyword", "wedding"], "XMP:PersonInImage": ["Maria"], "XMP:RegionAppliedToDimensionsW": 1526, "XMP:RegionAppliedToDimensionsH": 1325, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Maria"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.41222959756851196], "XMP:RegionAreaY": [0.4221687614917755], "XMP:RegionAreaW": [0.3333342373371124], "XMP:RegionAreaH": [0.3839004122086291], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:07:27 17:33:28"}]
|
||||
@@ -62,6 +62,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1325</stDim:h>
|
||||
<stDim:w>1526</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"ImageDescription": "Bride Wedding day", "Description": "Bride Wedding day", "Caption-Abstract": "Bride Wedding day", "Keywords": ["Maria", "wedding"], "Subject": ["Maria", "wedding"], "TagsList": ["Maria", "wedding"], "PersonInImage": ["Maria"], "DateTimeOriginal": "2019:04:15 14:40:24", "CreateDate": "2019:04:15 14:40:24", "OffsetTimeOriginal": "-04:00", "DateCreated": "2019:04:15", "TimeCreated": "14:40:24-04:00", "ModifyDate": "2019:07:27 17:33:28"}]
|
||||
[{"ImageDescription": "Bride Wedding day", "Description": "Bride Wedding day", "Caption-Abstract": "Bride Wedding day", "Keywords": ["Maria", "wedding"], "Subject": ["Maria", "wedding"], "TagsList": ["Maria", "wedding"], "PersonInImage": ["Maria"], "RegionAppliedToDimensionsW": 1526, "RegionAppliedToDimensionsH": 1325, "RegionAppliedToDimensionsUnit": "pixel", "RegionName": ["Maria"], "RegionType": ["Face"], "RegionAreaX": [0.41222959756851196], "RegionAreaY": [0.4221687614917755], "RegionAreaW": [0.3333342373371124], "RegionAreaH": [0.3839004122086291], "RegionAreaUnit": ["normalized"], "RegionPersonDisplayName": ["Maria"], "DateTimeOriginal": "2019:04:15 14:40:24", "CreateDate": "2019:04:15 14:40:24", "OffsetTimeOriginal": "-04:00", "DateCreated": "2019:04:15", "TimeCreated": "14:40:24-04:00", "ModifyDate": "2019:07:27 17:33:28"}]
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["Maria", "wedding"], "XMP:Subject": ["Maria", "wedding"], "XMP:TagsList": ["Maria", "wedding"], "XMP:PersonInImage": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:07:27 17:33:28"}]
|
||||
[{"EXIF:ImageDescription": "Bride Wedding day", "XMP:Description": "Bride Wedding day", "IPTC:Caption-Abstract": "Bride Wedding day", "IPTC:Keywords": ["Maria", "wedding"], "XMP:Subject": ["Maria", "wedding"], "XMP:TagsList": ["Maria", "wedding"], "XMP:PersonInImage": ["Maria"], "XMP:RegionAppliedToDimensionsW": 1526, "XMP:RegionAppliedToDimensionsH": 1325, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Maria"], "XMP:RegionType": ["Face"], "XMP:RegionAreaX": [0.41222959756851196], "XMP:RegionAreaY": [0.4221687614917755], "XMP:RegionAreaW": [0.3333342373371124], "XMP:RegionAreaH": [0.3839004122086291], "XMP:RegionAreaUnit": ["normalized"], "XMP:RegionPersonDisplayName": ["Maria"], "EXIF:DateTimeOriginal": "2019:04:15 14:40:24", "EXIF:CreateDate": "2019:04:15 14:40:24", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2019:04:15", "IPTC:TimeCreated": "14:40:24-04:00", "EXIF:ModifyDate": "2019:07:27 17:33:28"}]
|
||||
@@ -54,6 +54,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1325</stDim:h>
|
||||
<stDim:w>1526</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "IPTC:Caption-Abstract": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:ObjectName": "Can we carry this?", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie", "Suzy"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]
|
||||
[{"EXIF:ImageDescription": "Girls with pumpkins", "XMP:Description": "Girls with pumpkins", "IPTC:Caption-Abstract": "Girls with pumpkins", "XMP:Title": "Can we carry this?", "IPTC:ObjectName": "Can we carry this?", "IPTC:Keywords": ["Kids"], "XMP:Subject": ["Kids"], "XMP:TagsList": ["Kids"], "XMP:PersonInImage": ["Katie", "Suzy"], "XMP:RegionAppliedToDimensionsW": 2048, "XMP:RegionAppliedToDimensionsH": 1365, "XMP:RegionAppliedToDimensionsUnit": "pixel", "XMP:RegionName": ["Suzy", "Katie"], "XMP:RegionType": ["Face", "Face"], "XMP:RegionAreaX": [0.3205035626888275, 0.7158178221434355], "XMP:RegionAreaY": [0.33566537871956825, 0.4209024980664253], "XMP:RegionAreaW": [0.07409769326841342, 0.06201007632625988], "XMP:RegionAreaH": [0.11117368191480637, 0.09303782880306244], "XMP:RegionAreaUnit": ["normalized", "normalized"], "XMP:RegionPersonDisplayName": ["Suzy", "Katie"], "EXIF:DateTimeOriginal": "2018:09:28 15:35:49", "EXIF:CreateDate": "2018:09:28 15:35:49", "EXIF:OffsetTimeOriginal": "-04:00", "IPTC:DateCreated": "2018:09:28", "IPTC:TimeCreated": "15:35:49-04:00", "EXIF:ModifyDate": "2018:09:28 15:35:49"}]
|
||||
@@ -53,6 +53,8 @@
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>1365</stDim:h>
|
||||
<stDim:w>2048</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user