Compare commits

...

4 Commits

Author SHA1 Message Date
Rhet Turnbull
5b9547669e Add --cleanup files to report, #395 2021-03-14 14:58:35 -07:00
allcontributors[bot]
35b5bbd13d docs: add AaronVanGeffen as a contributor (#398)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2021-03-14 12:19:26 -07:00
Aaron van Geffen
6870ad0d8e Use original filename to export photos by default (#396)
* Use original filename to export photos by default, #176

* Fixed edited filename to also use original_filename if none provided.

* Rolled back previous change due to test failures

* Use original filename for edited file exports as well

Co-authored-by: Rhet Turnbull <rturnbull@gmail.com>
2021-03-14 12:19:05 -07:00
Rhet Turnbull
17ac5949e1 Updated docs for --cleanup, #394 2021-03-14 12:16:26 -07:00
38 changed files with 2868 additions and 542 deletions

View File

@@ -184,6 +184,15 @@
"contributions": [ "contributions": [
"code" "code"
] ]
},
{
"login": "AaronVanGeffen",
"name": "Aaron van Geffen",
"avatar_url": "https://avatars.githubusercontent.com/u/604665?v=4",
"profile": "https://aaronweb.net/",
"contributions": [
"code"
]
} }
], ],
"contributorsPerLine": 7, "contributorsPerLine": 7,

153
README.md
View File

@@ -4,7 +4,7 @@
[![tests](https://github.com/RhetTbull/osxphotos/workflows/Tests/badge.svg)](https://github.com/RhetTbull/osxphotos/workflows/Tests/badge.svg) [![tests](https://github.com/RhetTbull/osxphotos/workflows/Tests/badge.svg)](https://github.com/RhetTbull/osxphotos/workflows/Tests/badge.svg)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/osxphotos) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/osxphotos)
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section --> <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-19-orange.svg?style=flat)](#contributors) [![All Contributors](https://img.shields.io/badge/all_contributors-20-orange.svg?style=flat)](#contributors)
<!-- ALL-CONTRIBUTORS-BADGE:END --> <!-- ALL-CONTRIBUTORS-BADGE:END -->
OSXPhotos provides the ability to interact with and query Apple's Photos.app library on macOS. You can query the Photos library database — for example, file name, file path, and metadata such as keywords/tags, persons/faces, albums, etc. You can also easily export both the original and edited photos. OSXPhotos provides the ability to interact with and query Apple's Photos.app library on macOS. You can query the Photos library database — for example, file name, file path, and metadata such as keywords/tags, persons/faces, albums, etc. You can also easily export both the original and edited photos.
@@ -183,41 +183,52 @@ Options:
use in the following order: 1. last opened use in the following order: 1. last opened
library, 2. system library, 3. library, 2. system library, 3.
~/Pictures/Photos Library.photoslibrary ~/Pictures/Photos Library.photoslibrary
-V, --verbose Print verbose output. -V, --verbose Print verbose output.
--keyword KEYWORD Search for photos with keyword KEYWORD. If --keyword KEYWORD Search for photos with keyword KEYWORD. If
more than one keyword, treated as "OR", e.g. more than one keyword, treated as "OR", e.g.
find photos matching any keyword find photos matching any keyword
--person PERSON Search for photos with person PERSON. If more --person PERSON Search for photos with person PERSON. If more
than one person, treated as "OR", e.g. find than one person, treated as "OR", e.g. find
photos matching any person photos matching any person
--album ALBUM Search for photos in album ALBUM. If more than --album ALBUM Search for photos in album ALBUM. If more than
one album, treated as "OR", e.g. find photos one album, treated as "OR", e.g. find photos
matching any album matching any album
--folder FOLDER Search for photos in an album in folder --folder FOLDER Search for photos in an album in folder
FOLDER. If more than one folder, treated as FOLDER. If more than one folder, treated as
"OR", e.g. find photos in any FOLDER. Only "OR", e.g. find photos in any FOLDER. Only
searches top level folders (e.g. does not look searches top level folders (e.g. does not look
at subfolders) at subfolders)
--uuid UUID Search for photos with UUID(s). --uuid UUID Search for photos with UUID(s).
--uuid-from-file FILE Search for photos with UUID(s) loaded from --uuid-from-file FILE Search for photos with UUID(s) loaded from
FILE. Format is a single UUID per line. Lines FILE. Format is a single UUID per line. Lines
preceded with # are ignored. preceded with # are ignored.
--title TITLE Search for TITLE in title of photo. --title TITLE Search for TITLE in title of photo.
--no-title Search for photos with no title. --no-title Search for photos with no title.
--description DESC Search for DESC in description of photo. --description DESC Search for DESC in description of photo.
--no-description Search for photos with no description. --no-description Search for photos with no description.
--place PLACE Search for PLACE in photo's reverse --place PLACE Search for PLACE in photo's reverse
geolocation info geolocation info
--no-place Search for photos with no associated place --no-place Search for photos with no associated place
name info (no reverse geolocation info) name info (no reverse geolocation info)
--label LABEL Search for photos with image classification --label LABEL Search for photos with image classification
label LABEL (Photos 5 only). If more than one label LABEL (Photos 5 only). If more than one
label, treated as "OR", e.g. find photos label, treated as "OR", e.g. find photos
matching any label matching any label
--uti UTI Search for photos whose uniform type --uti UTI Search for photos whose uniform type
identifier (UTI) matches UTI identifier (UTI) matches UTI
-i, --ignore-case Case insensitive search for title, -i, --ignore-case Case insensitive search for title,
description, place, keyword, person, or album. description, place, keyword, person, or album.
--edited Search for photos that have been edited. --edited Search for photos that have been edited.
--external-edit Search for photos edited in external editor. --external-edit Search for photos edited in external editor.
--favorite Search for photos marked favorite. --favorite Search for photos marked favorite.
@@ -226,47 +237,61 @@ Options:
--not-hidden Search for photos not marked hidden. --not-hidden Search for photos not marked hidden.
--shared Search for photos in shared iCloud album --shared Search for photos in shared iCloud album
(Photos 5 only). (Photos 5 only).
--not-shared Search for photos not in shared iCloud album --not-shared Search for photos not in shared iCloud album
(Photos 5 only). (Photos 5 only).
--burst Search for photos that were taken in a burst. --burst Search for photos that were taken in a burst.
--not-burst Search for photos that are not part of a --not-burst Search for photos that are not part of a
burst. burst.
--live Search for Apple live photos --live Search for Apple live photos
--not-live Search for photos that are not Apple live --not-live Search for photos that are not Apple live
photos. photos.
--portrait Search for Apple portrait mode photos. --portrait Search for Apple portrait mode photos.
--not-portrait Search for photos that are not Apple portrait --not-portrait Search for photos that are not Apple portrait
mode photos. mode photos.
--screenshot Search for screenshot photos. --screenshot Search for screenshot photos.
--not-screenshot Search for photos that are not screenshot --not-screenshot Search for photos that are not screenshot
photos. photos.
--slow-mo Search for slow motion videos. --slow-mo Search for slow motion videos.
--not-slow-mo Search for photos that are not slow motion --not-slow-mo Search for photos that are not slow motion
videos. videos.
--time-lapse Search for time lapse videos. --time-lapse Search for time lapse videos.
--not-time-lapse Search for photos that are not time lapse --not-time-lapse Search for photos that are not time lapse
videos. videos.
--hdr Search for high dynamic range (HDR) photos. --hdr Search for high dynamic range (HDR) photos.
--not-hdr Search for photos that are not HDR photos. --not-hdr Search for photos that are not HDR photos.
--selfie Search for selfies (photos taken with front- --selfie Search for selfies (photos taken with front-
facing cameras). facing cameras).
--not-selfie Search for photos that are not selfies. --not-selfie Search for photos that are not selfies.
--panorama Search for panorama photos. --panorama Search for panorama photos.
--not-panorama Search for photos that are not panoramas. --not-panorama Search for photos that are not panoramas.
--has-raw Search for photos with both a jpeg and raw --has-raw Search for photos with both a jpeg and raw
version version
--only-movies Search only for movies (default searches both --only-movies Search only for movies (default searches both
images and movies). images and movies).
--only-photos Search only for photos/images (default --only-photos Search only for photos/images (default
searches both images and movies). searches both images and movies).
--from-date DATETIME Search by start item date, e.g. --from-date DATETIME Search by start item date, e.g.
2000-01-12T12:00:00, 2000-01-12T12:00:00,
2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO
8601). 8601).
--to-date DATETIME Search by end item date, e.g. --to-date DATETIME Search by end item date, e.g.
2000-01-12T12:00:00, 2000-01-12T12:00:00,
2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO
8601). 8601).
--has-comment Search for photos that have comments. --has-comment Search for photos that have comments.
--no-comment Search for photos with no comments. --no-comment Search for photos with no comments.
--has-likes Search for photos that have likes. --has-likes Search for photos that have likes.
@@ -274,17 +299,23 @@ Options:
--is-reference Search for photos that were imported as --is-reference Search for photos that were imported as
referenced files (not copied into Photos referenced files (not copied into Photos
library). library).
--in-album Search for photos that are in one or more --in-album Search for photos that are in one or more
albums. albums.
--not-in-album Search for photos that are not in any albums. --not-in-album Search for photos that are not in any albums.
--missing Export only photos missing from the Photos --missing Export only photos missing from the Photos
library; must be used with --download-missing. library; must be used with --download-missing.
--deleted Include photos from the 'Recently Deleted' --deleted Include photos from the 'Recently Deleted'
folder. folder.
--deleted-only Include only photos from the 'Recently --deleted-only Include only photos from the 'Recently
Deleted' folder. Deleted' folder.
--update Only export new or updated files. See notes --update Only export new or updated files. See notes
below on export and --update. below on export and --update.
--ignore-signature When used with '--update', ignores file --ignore-signature When used with '--update', ignores file
signature when updating files. This is useful signature when updating files. This is useful
if you have processed or edited exported if you have processed or edited exported
@@ -303,12 +334,15 @@ Options:
not; 3) if a sidecar does not exist for the not; 3) if a sidecar does not exist for the
photo, a sidecar will be written whether or photo, a sidecar will be written whether or
not the photo file was written or updated. not the photo file was written or updated.
--only-new If used with --update, ignores any previously --only-new If used with --update, ignores any previously
exported files, even if missing from the exported files, even if missing from the
export folder and only exports new files that export folder and only exports new files that
haven't previously been exported. haven't previously been exported.
--dry-run Dry run (test) the export but don't actually --dry-run Dry run (test) the export but don't actually
export any files; most useful with --verbose. export any files; most useful with --verbose.
--export-as-hardlink Hardlink files instead of copying them. Cannot --export-as-hardlink Hardlink files instead of copying them. Cannot
be used with --exiftool which creates copies be used with --exiftool which creates copies
of the files with embedded EXIF data. Note: on of the files with embedded EXIF data. Note: on
@@ -316,41 +350,53 @@ Options:
giving many of the same advantages as giving many of the same advantages as
hardlinks without having to use --export-as- hardlinks without having to use --export-as-
hardlink. hardlink.
--touch-file Sets the file's modification time to match --touch-file Sets the file's modification time to match
photo date. photo date.
--overwrite Overwrite existing files. Default behavior is --overwrite Overwrite existing files. Default behavior is
to add (1), (2), etc to filename if file to add (1), (2), etc to filename if file
already exists. Use this with caution as it already exists. Use this with caution as it
may create name collisions on export. (e.g. if may create name collisions on export. (e.g. if
two files happen to have the same name) two files happen to have the same name)
--export-by-date Automatically create output folders to --export-by-date Automatically create output folders to
organize photos by date created (e.g. organize photos by date created (e.g.
DEST/2019/12/20/photoname.jpg). DEST/2019/12/20/photoname.jpg).
--skip-edited Do not export edited version of photo if an --skip-edited Do not export edited version of photo if an
edited version exists. edited version exists.
--skip-original-if-edited Do not export original if there is an edited --skip-original-if-edited Do not export original if there is an edited
version (exports only the edited version). version (exports only the edited version).
--skip-bursts Do not export all associated burst images in --skip-bursts Do not export all associated burst images in
the library if a photo is a burst photo. the library if a photo is a burst photo.
--skip-live Do not export the associated live video --skip-live Do not export the associated live video
component of a live photo. component of a live photo.
--skip-raw Do not export associated raw images of a --skip-raw Do not export associated raw images of a
RAW+JPEG pair. Note: this does not skip raw RAW+JPEG pair. Note: this does not skip raw
photos if the raw photo does not have an photos if the raw photo does not have an
associated jpeg image (e.g. the raw file was associated jpeg image (e.g. the raw file was
imported to Photos without a jpeg preview). imported to Photos without a jpeg preview).
--current-name Use photo's current filename instead of --current-name Use photo's current filename instead of
original filename for export. Note: Starting original filename for export. Note: Starting
with Photos 5, all photos are renamed upon with Photos 5, all photos are renamed upon
import. By default, photos are exported with import. By default, photos are exported with
the the original name they had before import. the the original name they had before import.
--convert-to-jpeg Convert all non-jpeg images (e.g. raw, HEIC, --convert-to-jpeg Convert all non-jpeg images (e.g. raw, HEIC,
PNG, etc) to JPEG upon export. Only works if PNG, etc) to JPEG upon export. Only works if
your Mac has a GPU. your Mac has a GPU.
--jpeg-quality FLOAT RANGE Value in range 0.0 to 1.0 to use with --jpeg-quality FLOAT RANGE Value in range 0.0 to 1.0 to use with
--convert-to-jpeg. A value of 1.0 specifies --convert-to-jpeg. A value of 1.0 specifies
best quality, a value of 0.0 specifies maximum best quality, a value of 0.0 specifies maximum
compression. Defaults to 1.0 compression. Defaults to 1.0
--download-missing Attempt to download missing photos from --download-missing Attempt to download missing photos from
iCloud. The current implementation uses iCloud. The current implementation uses
Applescript to interact with Photos to export Applescript to interact with Photos to export
@@ -363,6 +409,7 @@ Options:
export all burst images; only the primary export all burst images; only the primary
photo will be exported--associated burst photo will be exported--associated burst
images will be skipped. images will be skipped.
--sidecar FORMAT Create sidecar for each photo exported; valid --sidecar FORMAT Create sidecar for each photo exported; valid
FORMAT values: xmp, json, exiftool; --sidecar FORMAT values: xmp, json, exiftool; --sidecar
xmp: create XMP sidecar used by Digikam, Adobe xmp: create XMP sidecar used by Digikam, Adobe
@@ -389,6 +436,7 @@ Options:
tags exported in the JSON and exiftool tags exported in the JSON and exiftool
sidecar, see '--exiftool'. See also '--ignore- sidecar, see '--exiftool'. See also '--ignore-
signature'. signature'.
--sidecar-drop-ext Drop the photo's extension when naming sidecar --sidecar-drop-ext Drop the photo's extension when naming sidecar
files. By default, sidecar files are named in files. By default, sidecar files are named in
format 'photo_filename.photo_ext.sidecar_ext', format 'photo_filename.photo_ext.sidecar_ext',
@@ -400,6 +448,7 @@ Options:
of different types but the same name in the of different types but the same name in the
output directory, e.g. 'IMG_1234.JPG' and output directory, e.g. 'IMG_1234.JPG' and
'IMG_1234.MOV'. 'IMG_1234.MOV'.
--exiftool Use exiftool to write metadata directly to --exiftool Use exiftool to write metadata directly to
exported photos. To use this option, exiftool exported photos. To use this option, exiftool
must be installed and in the path. exiftool must be installed and in the path. exiftool
@@ -421,8 +470,10 @@ Options:
QuickTime:ModifyDate (see also --ignore-date- QuickTime:ModifyDate (see also --ignore-date-
modified); QuickTime:GPSCoordinates; modified); QuickTime:GPSCoordinates;
UserData:GPSCoordinates. UserData:GPSCoordinates.
--exiftool-path EXIFTOOL_PATH Optionally specify path to exiftool; if not --exiftool-path EXIFTOOL_PATH Optionally specify path to exiftool; if not
provided, will look for exiftool in $PATH. provided, will look for exiftool in $PATH.
--exiftool-option OPTION Optional flag/option to pass to exiftool when --exiftool-option OPTION Optional flag/option to pass to exiftool when
using --exiftool. For example, --exiftool- using --exiftool. For example, --exiftool-
option '-m' to ignore minor warnings. Specify option '-m' to ignore minor warnings. Specify
@@ -432,21 +483,27 @@ Options:
full list of options. More than one option may full list of options. More than one option may
be specified by repeating the option, e.g. be specified by repeating the option, e.g.
--exiftool-option '-m' --exiftool-option '-F'. --exiftool-option '-m' --exiftool-option '-F'.
--exiftool-merge-keywords Merge any keywords found in the original file --exiftool-merge-keywords Merge any keywords found in the original file
with keywords used for '--exiftool' and '-- with keywords used for '--exiftool' and '--
sidecar'. sidecar'.
--exiftool-merge-persons Merge any persons found in the original file --exiftool-merge-persons Merge any persons found in the original file
with persons used for '--exiftool' and '-- with persons used for '--exiftool' and '--
sidecar'. sidecar'.
--ignore-date-modified If used with --exiftool or --sidecar, will --ignore-date-modified If used with --exiftool or --sidecar, will
ignore the photo modification date and set ignore the photo modification date and set
EXIF:ModifyDate to EXIF:DateTimeOriginal; this EXIF:ModifyDate to EXIF:DateTimeOriginal; this
is consistent with how Photos handles the is consistent with how Photos handles the
EXIF:ModifyDate tag. EXIF:ModifyDate tag.
--person-keyword Use person in image as keyword/tag when --person-keyword Use person in image as keyword/tag when
exporting metadata. exporting metadata.
--album-keyword Use album name as keyword/tag when exporting --album-keyword Use album name as keyword/tag when exporting
metadata. metadata.
--keyword-template TEMPLATE For use with --exiftool, --sidecar; specify a --keyword-template TEMPLATE For use with --exiftool, --sidecar; specify a
template string to use as keyword in the form template string to use as keyword in the form
'{name,DEFAULT}' This is the same format as '{name,DEFAULT}' This is the same format as
@@ -459,6 +516,7 @@ Options:
"{folder_album}" --keyword-template "{folder_album}" --keyword-template
"{created.year}". See '--replace-keywords' and "{created.year}". See '--replace-keywords' and
Templating System below. Templating System below.
--replace-keywords Replace keywords with any values specified --replace-keywords Replace keywords with any values specified
with --keyword-template. By default, with --keyword-template. By default,
--keyword-template will add keywords to any --keyword-template will add keywords to any
@@ -467,6 +525,7 @@ Options:
from --keyword-template will replace any from --keyword-template will replace any
existing keywords instead of adding additional existing keywords instead of adding additional
keywords. keywords.
--description-template TEMPLATE --description-template TEMPLATE
For use with --exiftool, --sidecar; specify a For use with --exiftool, --sidecar; specify a
template string to use as description in the template string to use as description in the
@@ -477,6 +536,7 @@ Options:
--description-template "{descr} exported with --description-template "{descr} exported with
osxphotos on {today.date}" See Templating osxphotos on {today.date}" See Templating
System below. System below.
--finder-tag-template TEMPLATE Set MacOS Finder tags to TEMPLATE. These tags --finder-tag-template TEMPLATE Set MacOS Finder tags to TEMPLATE. These tags
can be searched in the Finder or Spotlight can be searched in the Finder or Spotlight
with 'tag:tagname' format. For example, '-- with 'tag:tagname' format. For example, '--
@@ -485,11 +545,13 @@ Options:
TEMPLATE values by using '--finder-tag- TEMPLATE values by using '--finder-tag-
template' multiple times. See also '--finder- template' multiple times. See also '--finder-
tag-keywords and Extended Attributes below.'. tag-keywords and Extended Attributes below.'.
--finder-tag-keywords Set MacOS Finder tags to keywords; any --finder-tag-keywords Set MacOS Finder tags to keywords; any
keywords specified via '--keyword-template', ' keywords specified via '--keyword-template', '
--person-keyword', etc. will also be used as --person-keyword', etc. will also be used as
Finder tags. See also '--finder-tag-template Finder tags. See also '--finder-tag-template
and Extended Attributes below.'. and Extended Attributes below.'.
--xattr-template ATTRIBUTE TEMPLATE --xattr-template ATTRIBUTE TEMPLATE
Set extended attribute ATTRIBUTE to TEMPLATE Set extended attribute ATTRIBUTE to TEMPLATE
value. Valid attributes are: 'authors', value. Valid attributes are: 'authors',
@@ -500,16 +562,19 @@ Options:
findercomment "{title}; {descr}" See Extended findercomment "{title}; {descr}" See Extended
Attributes below for additional details on Attributes below for additional details on
this option. this option.
--directory DIRECTORY Optional template for specifying name of --directory DIRECTORY Optional template for specifying name of
output directory in the form '{name,DEFAULT}'. output directory in the form '{name,DEFAULT}'.
See below for additional details on templating See below for additional details on templating
system. system.
--filename FILENAME Optional template for specifying name of --filename FILENAME Optional template for specifying name of
output file in the form '{name,DEFAULT}'. File output file in the form '{name,DEFAULT}'. File
extension will be added automatically--do not extension will be added automatically--do not
include an extension in the FILENAME template. include an extension in the FILENAME template.
See below for additional details on templating See below for additional details on templating
system. system.
--jpeg-ext EXTENSION Specify file extension for JPEG files. Photos --jpeg-ext EXTENSION Specify file extension for JPEG files. Photos
uses .jpeg for edited images but many images uses .jpeg for edited images but many images
are imported with .jpg or .JPG which can are imported with .jpg or .JPG which can
@@ -519,12 +584,14 @@ Options:
exported JPEG images. Valid values are jpeg, exported JPEG images. Valid values are jpeg,
jpg, JPEG, JPG; e.g. '--jpeg-ext jpg' to use jpg, JPEG, JPG; e.g. '--jpeg-ext jpg' to use
'.jpg' for all JPEGs. '.jpg' for all JPEGs.
--strip Optionally strip leading and trailing --strip Optionally strip leading and trailing
whitespace from any rendered templates. For whitespace from any rendered templates. For
example, if --filename template is "{title,} example, if --filename template is "{title,}
{original_name}" and image has no title, {original_name}" and image has no title,
resulting file would have a leading space but resulting file would have a leading space but
if used with --strip, this will be removed. if used with --strip, this will be removed.
--edited-suffix SUFFIX Optional suffix template for naming edited --edited-suffix SUFFIX Optional suffix template for naming edited
photos. Default name for edited photos is in photos. Default name for edited photos is in
form 'photoname_edited.ext'. For example, with form 'photoname_edited.ext'. For example, with
@@ -534,6 +601,7 @@ Options:
suffix is '_edited'. Multi-value templates suffix is '_edited'. Multi-value templates
(see Templating System) are not permitted with (see Templating System) are not permitted with
--edited-suffix. --edited-suffix.
--original-suffix SUFFIX Optional suffix template for naming original --original-suffix SUFFIX Optional suffix template for naming original
photos. Default name for original photos is photos. Default name for original photos is
in form 'filename.ext'. For example, with '-- in form 'filename.ext'. For example, with '--
@@ -542,9 +610,11 @@ Options:
default suffix is '' (no suffix). Multi-value default suffix is '' (no suffix). Multi-value
templates (see Templating System) are not templates (see Templating System) are not
permitted with --original-suffix. permitted with --original-suffix.
--use-photos-export Force the use of AppleScript or PhotoKit to --use-photos-export Force the use of AppleScript or PhotoKit to
export even if not missing (see also '-- export even if not missing (see also '--
download-missing' and '--use-photokit'). download-missing' and '--use-photokit').
--use-photokit Use with '--download-missing' or '--use- --use-photokit Use with '--download-missing' or '--use-
photos-export' to use direct Photos interface photos-export' to use direct Photos interface
instead of AppleScript to export. Highly instead of AppleScript to export. Highly
@@ -552,14 +622,23 @@ Options:
iTerm2 (use with Terminal.app). This is faster iTerm2 (use with Terminal.app). This is faster
and more reliable than the default AppleScript and more reliable than the default AppleScript
interface. interface.
--report <path to export report> --report <path to export report>
Write a CSV formatted report of all files that Write a CSV formatted report of all files that
were exported. were exported.
--cleanup Cleanup export directory by deleting any files --cleanup Cleanup export directory by deleting any files
which were not included in this export set. which were not included in this export set.
For example, photos which had previously been For example, photos which had previously been
exported and were subsequently deleted in exported and were subsequently deleted in
Photos. Photos. WARNING: --cleanup will delete *any*
files in the export directory that were not
exported by osxphotos, for example, your own
scripts or other files. Be sure this is what
you intend before using --cleanup. Use --dry-
run with --cleanup first if you're not
certain.
--exportdb EXPORTDB_FILE Specify alternate name for database file which --exportdb EXPORTDB_FILE Specify alternate name for database file which
stores state information for export and stores state information for export and
--update. If --exportdb is not specified, --update. If --exportdb is not specified,
@@ -568,6 +647,7 @@ Options:
directory. Must be specified as filename directory. Must be specified as filename
only, not a path, as export database will be only, not a path, as export database will be
saved in export directory. saved in export directory.
--load-config <config file path> --load-config <config file path>
Load options from file as written with --save- Load options from file as written with --save-
config. This allows you to save a complex config. This allows you to save a complex
@@ -579,9 +659,11 @@ Options:
line options are used in conjunction with line options are used in conjunction with
--load-config, they will override the --load-config, they will override the
corresponding values in the config file. corresponding values in the config file.
--save-config <config file path> --save-config <config file path>
Save options to file for use with --load- Save options to file for use with --load-
config. File format is TOML. config. File format is TOML.
--help Show this message and exit. --help Show this message and exit.
** Export ** ** Export **
@@ -636,25 +718,32 @@ The following attributes may be used with '--xattr-template':
authors The author, or authors, of the contents of the file. A list of authors The author, or authors, of the contents of the file. A list of
strings. (com.apple.metadata:kMDItemAuthors) strings. (com.apple.metadata:kMDItemAuthors)
comment A comment related to the file. This differs from the Finder comment A comment related to the file. This differs from the Finder
comment, kMDItemFinderComment. A string. comment, kMDItemFinderComment. A string.
(com.apple.metadata:kMDItemComment) (com.apple.metadata:kMDItemComment)
copyright The copyright owner of the file contents. A string. copyright The copyright owner of the file contents. A string.
(com.apple.metadata:kMDItemCopyright) (com.apple.metadata:kMDItemCopyright)
description A description of the content of the resource. The description description A description of the content of the resource. The description
may include an abstract, table of contents, reference to a may include an abstract, table of contents, reference to a
graphical representation of content or a free-text account of graphical representation of content or a free-text account of
the content. A string. (com.apple.metadata:kMDItemDescription) the content. A string. (com.apple.metadata:kMDItemDescription)
findercomment Finder comments for this file. A string. findercomment Finder comments for this file. A string.
(com.apple.metadata:kMDItemFinderComment) (com.apple.metadata:kMDItemFinderComment)
headline A publishable entry providing a synopsis of the contents of the headline A publishable entry providing a synopsis of the contents of the
file. A string. (com.apple.metadata:kMDItemHeadline) file. A string. (com.apple.metadata:kMDItemHeadline)
keywords Keywords associated with this file. For example, “Birthday”, keywords Keywords associated with this file. For example, “Birthday”,
“Important”, etc. This differs from Finder tags “Important”, etc. This differs from Finder tags
(_kMDItemUserTags) which are keywords/tags shown in the Finder (_kMDItemUserTags) which are keywords/tags shown in the Finder
and searchable in Spotlight using "tag:tag_name". A list of and searchable in Spotlight using "tag:tag_name". A list of
strings. (com.apple.metadata:kMDItemKeywords) strings. (com.apple.metadata:kMDItemKeywords)
For additional information on extended attributes see: https://developer.apple.c For additional information on extended attributes see: https://developer.apple.c
om/documentation/coreservices/file_metadata/mditem/common_metadata_attribute_key om/documentation/coreservices/file_metadata/mditem/common_metadata_attribute_key
s s
@@ -820,6 +909,7 @@ Substitution Description
{name} Current filename of the photo {name} Current filename of the photo
{original_name} Photo's original filename when imported to {original_name} Photo's original filename when imported to
Photos Photos
{title} Title of the photo {title} Title of the photo
{descr} Description of the photo {descr} Description of the photo
{media_type} Special media type resolved in this {media_type} Special media type resolved in this
@@ -829,30 +919,41 @@ Substitution Description
'video' if no special type. Customize one or 'video' if no special type. Customize one or
more media types using format: '{media_type,vi more media types using format: '{media_type,vi
deo=vidéo;time_lapse=vidéo_accélérée}' deo=vidéo;time_lapse=vidéo_accélérée}'
{photo_or_video} 'photo' or 'video' depending on what type the {photo_or_video} 'photo' or 'video' depending on what type the
image is. To customize, use default value as image is. To customize, use default value as
in '{photo_or_video,photo=fotos;video=videos}' in '{photo_or_video,photo=fotos;video=videos}'
{hdr} Photo is HDR?; True/False value, use in format {hdr} Photo is HDR?; True/False value, use in format
'{hdr?VALUE_IF_TRUE,VALUE_IF_FALSE}' '{hdr?VALUE_IF_TRUE,VALUE_IF_FALSE}'
{edited} Photo has been edited (has adjustments)?; {edited} Photo has been edited (has adjustments)?;
True/False value, use in format True/False value, use in format
'{edited?VALUE_IF_TRUE,VALUE_IF_FALSE}' '{edited?VALUE_IF_TRUE,VALUE_IF_FALSE}'
{created.date} Photo's creation date in ISO format, e.g. {created.date} Photo's creation date in ISO format, e.g.
'2020-03-22' '2020-03-22'
{created.year} 4-digit year of photo creation time {created.year} 4-digit year of photo creation time
{created.yy} 2-digit year of photo creation time {created.yy} 2-digit year of photo creation time
{created.mm} 2-digit month of the photo creation time (zero {created.mm} 2-digit month of the photo creation time (zero
padded) padded)
{created.month} Month name in user's locale of the photo {created.month} Month name in user's locale of the photo
creation time creation time
{created.mon} Month abbreviation in the user's locale of the {created.mon} Month abbreviation in the user's locale of the
photo creation time photo creation time
{created.dd} 2-digit day of the month (zero padded) of {created.dd} 2-digit day of the month (zero padded) of
photo creation time photo creation time
{created.dow} Day of week in user's locale of the photo {created.dow} Day of week in user's locale of the photo
creation time creation time
{created.doy} 3-digit day of year (e.g Julian day) of photo {created.doy} 3-digit day of year (e.g Julian day) of photo
creation time, starting from 1 (zero padded) creation time, starting from 1 (zero padded)
{created.hour} 2-digit hour of the photo creation time {created.hour} 2-digit hour of the photo creation time
{created.min} 2-digit minute of the photo creation time {created.min} 2-digit minute of the photo creation time
{created.sec} 2-digit second of the photo creation time {created.sec} 2-digit second of the photo creation time
@@ -865,38 +966,51 @@ Substitution Description
no template will return null value. See no template will return null value. See
https://strftime.org/ for help on strftime https://strftime.org/ for help on strftime
templates. templates.
{modified.date} Photo's modification date in ISO format, e.g. {modified.date} Photo's modification date in ISO format, e.g.
'2020-03-22'; uses creation date if photo is '2020-03-22'; uses creation date if photo is
not modified not modified
{modified.year} 4-digit year of photo modification time; uses {modified.year} 4-digit year of photo modification time; uses
creation date if photo is not modified creation date if photo is not modified
{modified.yy} 2-digit year of photo modification time; uses {modified.yy} 2-digit year of photo modification time; uses
creation date if photo is not modified creation date if photo is not modified
{modified.mm} 2-digit month of the photo modification time {modified.mm} 2-digit month of the photo modification time
(zero padded); uses creation date if photo is (zero padded); uses creation date if photo is
not modified not modified
{modified.month} Month name in user's locale of the photo {modified.month} Month name in user's locale of the photo
modification time; uses creation date if photo modification time; uses creation date if photo
is not modified is not modified
{modified.mon} Month abbreviation in the user's locale of the {modified.mon} Month abbreviation in the user's locale of the
photo modification time; uses creation date if photo modification time; uses creation date if
photo is not modified photo is not modified
{modified.dd} 2-digit day of the month (zero padded) of the {modified.dd} 2-digit day of the month (zero padded) of the
photo modification time; uses creation date if photo modification time; uses creation date if
photo is not modified photo is not modified
{modified.dow} Day of week in user's locale of the photo {modified.dow} Day of week in user's locale of the photo
modification time; uses creation date if photo modification time; uses creation date if photo
is not modified is not modified
{modified.doy} 3-digit day of year (e.g Julian day) of photo {modified.doy} 3-digit day of year (e.g Julian day) of photo
modification time, starting from 1 (zero modification time, starting from 1 (zero
padded); uses creation date if photo is not padded); uses creation date if photo is not
modified modified
{modified.hour} 2-digit hour of the photo modification time; {modified.hour} 2-digit hour of the photo modification time;
uses creation date if photo is not modified uses creation date if photo is not modified
{modified.min} 2-digit minute of the photo modification time; {modified.min} 2-digit minute of the photo modification time;
uses creation date if photo is not modified uses creation date if photo is not modified
{modified.sec} 2-digit second of the photo modification time; {modified.sec} 2-digit second of the photo modification time;
uses creation date if photo is not modified uses creation date if photo is not modified
{modified.strftime} Apply strftime template to file modification {modified.strftime} Apply strftime template to file modification
date/time. Should be used in form date/time. Should be used in form
{modified.strftime,TEMPLATE} where TEMPLATE is {modified.strftime,TEMPLATE} where TEMPLATE is
@@ -907,21 +1021,28 @@ Substitution Description
creation date if photo is not modified. See creation date if photo is not modified. See
https://strftime.org/ for help on strftime https://strftime.org/ for help on strftime
templates. templates.
{today.date} Current date in iso format, e.g. '2020-03-22' {today.date} Current date in iso format, e.g. '2020-03-22'
{today.year} 4-digit year of current date {today.year} 4-digit year of current date
{today.yy} 2-digit year of current date {today.yy} 2-digit year of current date
{today.mm} 2-digit month of the current date (zero {today.mm} 2-digit month of the current date (zero
padded) padded)
{today.month} Month name in user's locale of the current {today.month} Month name in user's locale of the current
date date
{today.mon} Month abbreviation in the user's locale of the {today.mon} Month abbreviation in the user's locale of the
current date current date
{today.dd} 2-digit day of the month (zero padded) of {today.dd} 2-digit day of the month (zero padded) of
current date current date
{today.dow} Day of week in user's locale of the current {today.dow} Day of week in user's locale of the current
date date
{today.doy} 3-digit day of year (e.g Julian day) of {today.doy} 3-digit day of year (e.g Julian day) of
current date, starting from 1 (zero padded) current date, starting from 1 (zero padded)
{today.hour} 2-digit hour of the current date {today.hour} 2-digit hour of the current date
{today.min} 2-digit minute of the current date {today.min} 2-digit minute of the current date
{today.sec} 2-digit second of the current date {today.sec} 2-digit second of the current date
@@ -934,51 +1055,70 @@ Substitution Description
no template will return null value. See no template will return null value. See
https://strftime.org/ for help on strftime https://strftime.org/ for help on strftime
templates. templates.
{place.name} Place name from the photo's reverse {place.name} Place name from the photo's reverse
geolocation data, as displayed in Photos geolocation data, as displayed in Photos
{place.country_code} The ISO country code from the photo's reverse {place.country_code} The ISO country code from the photo's reverse
geolocation data geolocation data
{place.name.country} Country name from the photo's reverse {place.name.country} Country name from the photo's reverse
geolocation data geolocation data
{place.name.state_province} State or province name from the photo's {place.name.state_province} State or province name from the photo's
reverse geolocation data reverse geolocation data
{place.name.city} City or locality name from the photo's reverse {place.name.city} City or locality name from the photo's reverse
geolocation data geolocation data
{place.name.area_of_interest} Area of interest name (e.g. landmark or public {place.name.area_of_interest} Area of interest name (e.g. landmark or public
place) from the photo's reverse geolocation place) from the photo's reverse geolocation
data data
{place.address} Postal address from the photo's reverse {place.address} Postal address from the photo's reverse
geolocation data, e.g. '2007 18th St NW, geolocation data, e.g. '2007 18th St NW,
Washington, DC 20009, United States' Washington, DC 20009, United States'
{place.address.street} Street part of the postal address, e.g. '2007 {place.address.street} Street part of the postal address, e.g. '2007
18th St NW' 18th St NW'
{place.address.city} City part of the postal address, e.g. {place.address.city} City part of the postal address, e.g.
'Washington' 'Washington'
{place.address.state_province} State/province part of the postal address, {place.address.state_province} State/province part of the postal address,
e.g. 'DC' e.g. 'DC'
{place.address.postal_code} Postal code part of the postal address, e.g. {place.address.postal_code} Postal code part of the postal address, e.g.
'20009' '20009'
{place.address.country} Country name of the postal address, e.g. {place.address.country} Country name of the postal address, e.g.
'United States' 'United States'
{place.address.country_code} ISO country code of the postal address, e.g. {place.address.country_code} ISO country code of the postal address, e.g.
'US' 'US'
{searchinfo.season} Season of the year associated with a photo, {searchinfo.season} Season of the year associated with a photo,
e.g. 'Summer'; (Photos 5+ only, applied e.g. 'Summer'; (Photos 5+ only, applied
automatically by Photos' image categorization automatically by Photos' image categorization
algorithms). algorithms).
{exif.camera_make} Camera make from original photo's EXIF {exif.camera_make} Camera make from original photo's EXIF
information as imported by Photos, e.g. information as imported by Photos, e.g.
'Apple' 'Apple'
{exif.camera_model} Camera model from original photo's EXIF {exif.camera_model} Camera model from original photo's EXIF
information as imported by Photos, e.g. information as imported by Photos, e.g.
'iPhone 6s' 'iPhone 6s'
{exif.lens_model} Lens model from original photo's EXIF {exif.lens_model} Lens model from original photo's EXIF
information as imported by Photos, e.g. information as imported by Photos, e.g.
'iPhone 6s back camera 4.15mm f/2.2' 'iPhone 6s back camera 4.15mm f/2.2'
{uuid} Photo's internal universally unique identifier {uuid} Photo's internal universally unique identifier
(UUID) for the photo, a 36-character string (UUID) for the photo, a 36-character string
unique to the photo, e.g. unique to the photo, e.g.
'128FB4C6-0B16-4E7D-9108-FB2E90DA1546' '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'
{comma} A comma: ',' {comma} A comma: ','
{semicolon} A semicolon: ';' {semicolon} A semicolon: ';'
{pipe} A vertical pipe: '|' {pipe} A vertical pipe: '|'
@@ -1001,13 +1141,16 @@ Substitution Description
{folder_album} Folder path + album photo is contained in. e.g. {folder_album} Folder path + album photo is contained in. e.g.
'Folder/Subfolder/Album' or just 'Album' if no 'Folder/Subfolder/Album' or just 'Album' if no
enclosing folder enclosing folder
{keyword} Keyword(s) assigned to photo {keyword} Keyword(s) assigned to photo
{person} Person(s) / face(s) in a photo {person} Person(s) / face(s) in a photo
{label} Image categorization label associated with a photo {label} Image categorization label associated with a photo
(Photos 5+ only) (Photos 5+ only)
{label_normalized} All lower case version of 'label' (Photos 5+ only) {label_normalized} All lower case version of 'label' (Photos 5+ only)
{comment} Comment(s) on shared Photos; format is 'Person name: {comment} Comment(s) on shared Photos; format is 'Person name:
comment text' (Photos 5+ only) comment text' (Photos 5+ only)
{exiftool} Format: '{exiftool:GROUP:TAGNAME}'; use exiftool {exiftool} Format: '{exiftool:GROUP:TAGNAME}'; use exiftool
(https://exiftool.org) to extract metadata, in form (https://exiftool.org) to extract metadata, in form
GROUP:TAGNAME, from image. E.g. GROUP:TAGNAME, from image. E.g.
@@ -1017,21 +1160,26 @@ Substitution Description
names. You must specify group (e.g. EXIF, IPTC, etc) names. You must specify group (e.g. EXIF, IPTC, etc)
as used in `exiftool -G`. exiftool must be installed as used in `exiftool -G`. exiftool must be installed
in the path to use this template. in the path to use this template.
{searchinfo.holiday} Holiday names associated with a photo, e.g. {searchinfo.holiday} Holiday names associated with a photo, e.g.
'Christmas Day'; (Photos 5+ only, applied 'Christmas Day'; (Photos 5+ only, applied
automatically by Photos' image categorization automatically by Photos' image categorization
algorithms). algorithms).
{searchinfo.activity} Activities associated with a photo, e.g. 'Sporting {searchinfo.activity} Activities associated with a photo, e.g. 'Sporting
Event'; (Photos 5+ only, applied automatically by Event'; (Photos 5+ only, applied automatically by
Photos' image categorization algorithms). Photos' image categorization algorithms).
{searchinfo.venue} Venues associated with a photo, e.g. name of {searchinfo.venue} Venues associated with a photo, e.g. name of
restaurant; (Photos 5+ only, applied automatically by restaurant; (Photos 5+ only, applied automatically by
Photos' image categorization algorithms). Photos' image categorization algorithms).
{searchinfo.venue_type} Venue types associated with a photo, e.g. {searchinfo.venue_type} Venue types associated with a photo, e.g.
'Restaurant'; (Photos 5+ only, applied automatically 'Restaurant'; (Photos 5+ only, applied automatically
by Photos' image categorization algorithms). by Photos' image categorization algorithms).
``` ```
<!-- OSXPHOTOS-EXPORT-USAGE:END --> <!-- OSXPHOTOS-EXPORT-USAGE:END -->
@@ -2728,6 +2876,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center"><a href="https://github.com/martinhrpi"><img src="https://avatars2.githubusercontent.com/u/19407684?v=4?s=75" width="75px;" alt=""/><br /><sub><b>Martin</b></sub></a><br /><a href="#research-martinhrpi" title="Research">🔬</a> <a href="#userTesting-martinhrpi" title="User Testing">📓</a></td> <td align="center"><a href="https://github.com/martinhrpi"><img src="https://avatars2.githubusercontent.com/u/19407684?v=4?s=75" width="75px;" alt=""/><br /><sub><b>Martin</b></sub></a><br /><a href="#research-martinhrpi" title="Research">🔬</a> <a href="#userTesting-martinhrpi" title="User Testing">📓</a></td>
<td align="center"><a href="https://github.com/davidjroos"><img src="https://avatars.githubusercontent.com/u/15630844?v=4?s=75" width="75px;" alt=""/><br /><sub><b>davidjroos </b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/commits?author=davidjroos" title="Documentation">📖</a></td> <td align="center"><a href="https://github.com/davidjroos"><img src="https://avatars.githubusercontent.com/u/15630844?v=4?s=75" width="75px;" alt=""/><br /><sub><b>davidjroos </b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/commits?author=davidjroos" title="Documentation">📖</a></td>
<td align="center"><a href="https://neilpa.me"><img src="https://avatars.githubusercontent.com/u/42419?v=4?s=75" width="75px;" alt=""/><br /><sub><b>Neil Pankey</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/commits?author=neilpa" title="Code">💻</a></td> <td align="center"><a href="https://neilpa.me"><img src="https://avatars.githubusercontent.com/u/42419?v=4?s=75" width="75px;" alt=""/><br /><sub><b>Neil Pankey</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/commits?author=neilpa" title="Code">💻</a></td>
<td align="center"><a href="https://aaronweb.net/"><img src="https://avatars.githubusercontent.com/u/604665?v=4?s=75" width="75px;" alt=""/><br /><sub><b>Aaron van Geffen</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/commits?author=AaronVanGeffen" title="Code">💻</a></td>
</tr> </tr>
</table> </table>

View File

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

View File

@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Overview: module code &#8212; osxphotos 0.41.0 documentation</title> <title>Overview: module code &#8212; osxphotos 0.41.2 documentation</title>
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../_static/alabaster.css" type="text/css" /> <link rel="stylesheet" href="../_static/alabaster.css" type="text/css" />
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> <script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
@@ -93,7 +93,7 @@
&copy;2021, Rhet Turnbull. &copy;2021, Rhet Turnbull.
| |
Powered by <a href="http://sphinx-doc.org/">Sphinx 3.4.3</a> Powered by <a href="http://sphinx-doc.org/">Sphinx 3.5.2</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a> &amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
</div> </div>

View File

@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>osxphotos.photoinfo._photoinfo_export &#8212; osxphotos 0.41.0 documentation</title> <title>osxphotos.photoinfo._photoinfo_export &#8212; osxphotos 0.41.2 documentation</title>
<link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" /> <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../../../_static/alabaster.css" type="text/css" /> <link rel="stylesheet" href="../../../_static/alabaster.css" type="text/css" />
<script id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script> <script id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
@@ -508,6 +508,9 @@
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">jpeg_ext</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">jpeg_ext</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="p">):</span> <span class="p">):</span>
<span class="sd">&quot;&quot;&quot;export photo, like export but with update and dry_run options</span> <span class="sd">&quot;&quot;&quot;export photo, like export but with update and dry_run options</span>
<span class="sd"> dest: must be valid destination path or exception raised</span> <span class="sd"> dest: must be valid destination path or exception raised</span>
@@ -560,6 +563,9 @@
<span class="sd"> merge_exif_keywords: boolean; if True, merged keywords found in file&#39;s exif data (requires exiftool)</span> <span class="sd"> merge_exif_keywords: boolean; if True, merged keywords found in file&#39;s exif data (requires exiftool)</span>
<span class="sd"> merge_exif_persons: boolean; if True, merged persons found in file&#39;s exif data (requires exiftool)</span> <span class="sd"> merge_exif_persons: boolean; if True, merged persons found in file&#39;s exif data (requires exiftool)</span>
<span class="sd"> jpeg_ext: if set, will use this value for extension on jpegs converted to jpeg with convert_to_jpeg; if not set, uses jpeg; do not include the leading &quot;.&quot;</span> <span class="sd"> jpeg_ext: if set, will use this value for extension on jpegs converted to jpeg with convert_to_jpeg; if not set, uses jpeg; do not include the leading &quot;.&quot;</span>
<span class="sd"> persons: if True, include persons in exported metadata</span>
<span class="sd"> location: if True, include location in exported metadata</span>
<span class="sd"> replace_keywords: if True, keyword_template replaces any keywords, otherwise it&#39;s additive</span>
<span class="sd"> Returns: ExportResults class </span> <span class="sd"> Returns: ExportResults class </span>
<span class="sd"> ExportResults has attributes: </span> <span class="sd"> ExportResults has attributes: </span>
@@ -974,6 +980,9 @@
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span>
<span class="n">filename</span><span class="o">=</span><span class="n">dest</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="n">dest</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="n">persons</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="n">location</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="n">replace_keywords</span><span class="p">,</span>
<span class="p">)</span> <span class="p">)</span>
<span class="n">sidecars</span><span class="o">.</span><span class="n">append</span><span class="p">(</span> <span class="n">sidecars</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
<span class="p">(</span> <span class="p">(</span>
@@ -997,6 +1006,9 @@
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span>
<span class="n">filename</span><span class="o">=</span><span class="n">dest</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="n">dest</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="n">persons</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="n">location</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="n">replace_keywords</span><span class="p">,</span>
<span class="p">)</span> <span class="p">)</span>
<span class="n">sidecars</span><span class="o">.</span><span class="n">append</span><span class="p">(</span> <span class="n">sidecars</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
<span class="p">(</span> <span class="p">(</span>
@@ -1016,6 +1028,9 @@
<span class="n">keyword_template</span><span class="o">=</span><span class="n">keyword_template</span><span class="p">,</span> <span class="n">keyword_template</span><span class="o">=</span><span class="n">keyword_template</span><span class="p">,</span>
<span class="n">description_template</span><span class="o">=</span><span class="n">description_template</span><span class="p">,</span> <span class="n">description_template</span><span class="o">=</span><span class="n">description_template</span><span class="p">,</span>
<span class="n">extension</span><span class="o">=</span><span class="n">dest</span><span class="o">.</span><span class="n">suffix</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span> <span class="k">if</span> <span class="n">dest</span><span class="o">.</span><span class="n">suffix</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span> <span class="n">extension</span><span class="o">=</span><span class="n">dest</span><span class="o">.</span><span class="n">suffix</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span> <span class="k">if</span> <span class="n">dest</span><span class="o">.</span><span class="n">suffix</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="n">persons</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="n">location</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="n">replace_keywords</span><span class="p">,</span>
<span class="p">)</span> <span class="p">)</span>
<span class="n">sidecars</span><span class="o">.</span><span class="n">append</span><span class="p">(</span> <span class="n">sidecars</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
<span class="p">(</span> <span class="p">(</span>
@@ -1083,6 +1098,9 @@
<span class="n">ignore_date_modified</span><span class="o">=</span><span class="n">ignore_date_modified</span><span class="p">,</span> <span class="n">ignore_date_modified</span><span class="o">=</span><span class="n">ignore_date_modified</span><span class="p">,</span>
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="n">persons</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="n">location</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="n">replace_keywords</span><span class="p">,</span>
<span class="p">)</span> <span class="p">)</span>
<span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="n">old_data</span> <span class="o">!=</span> <span class="n">current_data</span><span class="p">:</span> <span class="k">if</span> <span class="n">old_data</span> <span class="o">!=</span> <span class="n">current_data</span><span class="p">:</span>
@@ -1103,6 +1121,9 @@
<span class="n">flags</span><span class="o">=</span><span class="n">exiftool_flags</span><span class="p">,</span> <span class="n">flags</span><span class="o">=</span><span class="n">exiftool_flags</span><span class="p">,</span>
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="n">persons</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="n">location</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="n">replace_keywords</span><span class="p">,</span>
<span class="p">)</span> <span class="p">)</span>
<span class="k">if</span> <span class="n">warning_</span><span class="p">:</span> <span class="k">if</span> <span class="n">warning_</span><span class="p">:</span>
<span class="n">all_results</span><span class="o">.</span><span class="n">exiftool_warning</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">exported_file</span><span class="p">,</span> <span class="n">warning_</span><span class="p">))</span> <span class="n">all_results</span><span class="o">.</span><span class="n">exiftool_warning</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">exported_file</span><span class="p">,</span> <span class="n">warning_</span><span class="p">))</span>
@@ -1120,6 +1141,9 @@
<span class="n">ignore_date_modified</span><span class="o">=</span><span class="n">ignore_date_modified</span><span class="p">,</span> <span class="n">ignore_date_modified</span><span class="o">=</span><span class="n">ignore_date_modified</span><span class="p">,</span>
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="n">persons</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="n">location</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="n">replace_keywords</span><span class="p">,</span>
<span class="p">),</span> <span class="p">),</span>
<span class="p">)</span> <span class="p">)</span>
<span class="n">export_db</span><span class="o">.</span><span class="n">set_stat_exif_for_file</span><span class="p">(</span> <span class="n">export_db</span><span class="o">.</span><span class="n">set_stat_exif_for_file</span><span class="p">(</span>
@@ -1142,6 +1166,9 @@
<span class="n">flags</span><span class="o">=</span><span class="n">exiftool_flags</span><span class="p">,</span> <span class="n">flags</span><span class="o">=</span><span class="n">exiftool_flags</span><span class="p">,</span>
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="n">persons</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="n">location</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="n">replace_keywords</span><span class="p">,</span>
<span class="p">)</span> <span class="p">)</span>
<span class="k">if</span> <span class="n">warning_</span><span class="p">:</span> <span class="k">if</span> <span class="n">warning_</span><span class="p">:</span>
<span class="n">all_results</span><span class="o">.</span><span class="n">exiftool_warning</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">exported_file</span><span class="p">,</span> <span class="n">warning_</span><span class="p">))</span> <span class="n">all_results</span><span class="o">.</span><span class="n">exiftool_warning</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">exported_file</span><span class="p">,</span> <span class="n">warning_</span><span class="p">))</span>
@@ -1159,6 +1186,9 @@
<span class="n">ignore_date_modified</span><span class="o">=</span><span class="n">ignore_date_modified</span><span class="p">,</span> <span class="n">ignore_date_modified</span><span class="o">=</span><span class="n">ignore_date_modified</span><span class="p">,</span>
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="n">persons</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="n">location</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="n">replace_keywords</span><span class="p">,</span>
<span class="p">),</span> <span class="p">),</span>
<span class="p">)</span> <span class="p">)</span>
<span class="n">export_db</span><span class="o">.</span><span class="n">set_stat_exif_for_file</span><span class="p">(</span> <span class="n">export_db</span><span class="o">.</span><span class="n">set_stat_exif_for_file</span><span class="p">(</span>
@@ -1378,6 +1408,9 @@
<span class="n">flags</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">flags</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="p">):</span> <span class="p">):</span>
<span class="sd">&quot;&quot;&quot;write exif data to image file at filepath</span> <span class="sd">&quot;&quot;&quot;write exif data to image file at filepath</span>
@@ -1388,6 +1421,9 @@
<span class="sd"> keyword_template: (list of strings); list of template strings to render as keywords</span> <span class="sd"> keyword_template: (list of strings); list of template strings to render as keywords</span>
<span class="sd"> ignore_date_modified: if True, sets EXIF:ModifyDate to EXIF:DateTimeOriginal even if date_modified is set</span> <span class="sd"> ignore_date_modified: if True, sets EXIF:ModifyDate to EXIF:DateTimeOriginal even if date_modified is set</span>
<span class="sd"> flags: optional list of exiftool flags to prepend to exiftool command when writing metadata (e.g. -m or -F)</span> <span class="sd"> flags: optional list of exiftool flags to prepend to exiftool command when writing metadata (e.g. -m or -F)</span>
<span class="sd"> persons: if True, write person data to metadata</span>
<span class="sd"> location: if True, write location data to metadata</span>
<span class="sd"> replace_keywords: if True, keyword_template replaces any keywords, otherwise it&#39;s additive</span>
<span class="sd"> Returns:</span> <span class="sd"> Returns:</span>
<span class="sd"> (warning, error) of warning and error strings if exiftool produces warnings or errors</span> <span class="sd"> (warning, error) of warning and error strings if exiftool produces warnings or errors</span>
@@ -1402,6 +1438,9 @@
<span class="n">ignore_date_modified</span><span class="o">=</span><span class="n">ignore_date_modified</span><span class="p">,</span> <span class="n">ignore_date_modified</span><span class="o">=</span><span class="n">ignore_date_modified</span><span class="p">,</span>
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="n">persons</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="n">location</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="n">replace_keywords</span><span class="p">,</span>
<span class="p">)</span> <span class="p">)</span>
<span class="k">with</span> <span class="n">ExifTool</span><span class="p">(</span><span class="n">filepath</span><span class="p">,</span> <span class="n">flags</span><span class="o">=</span><span class="n">flags</span><span class="p">,</span> <span class="n">exiftool</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_exiftool_path</span><span class="p">)</span> <span class="k">as</span> <span class="n">exiftool</span><span class="p">:</span> <span class="k">with</span> <span class="n">ExifTool</span><span class="p">(</span><span class="n">filepath</span><span class="p">,</span> <span class="n">flags</span><span class="o">=</span><span class="n">flags</span><span class="p">,</span> <span class="n">exiftool</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_exiftool_path</span><span class="p">)</span> <span class="k">as</span> <span class="n">exiftool</span><span class="p">:</span>
@@ -1424,6 +1463,9 @@
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">filename</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="p">):</span> <span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Return dict of EXIF details for building exiftool JSON sidecar or sending commands to ExifTool.</span> <span class="sd">&quot;&quot;&quot;Return dict of EXIF details for building exiftool JSON sidecar or sending commands to ExifTool.</span>
<span class="sd"> Does not include all the EXIF fields as those are likely already in the image.</span> <span class="sd"> Does not include all the EXIF fields as those are likely already in the image.</span>
@@ -1437,6 +1479,9 @@
<span class="sd"> ignore_date_modified: if True, sets EXIF:ModifyDate to EXIF:DateTimeOriginal even if date_modified is set</span> <span class="sd"> ignore_date_modified: if True, sets EXIF:ModifyDate to EXIF:DateTimeOriginal even if date_modified is set</span>
<span class="sd"> merge_exif_keywords: merge keywords in the file&#39;s exif metadata (requires exiftool)</span> <span class="sd"> merge_exif_keywords: merge keywords in the file&#39;s exif metadata (requires exiftool)</span>
<span class="sd"> merge_exif_persons: merge persons in the file&#39;s exif metadata (requires exiftool)</span> <span class="sd"> merge_exif_persons: merge persons in the file&#39;s exif metadata (requires exiftool)</span>
<span class="sd"> persons: if True, include person data</span>
<span class="sd"> location: if True, include location data</span>
<span class="sd"> replace_keywords: if True, keyword_template replaces any keywords, otherwise it&#39;s additive</span>
<span class="sd"> Returns: dict with exiftool tags / values</span> <span class="sd"> Returns: dict with exiftool tags / values</span>
@@ -1444,8 +1489,10 @@
<span class="sd"> EXIF:ImageDescription (may include template)</span> <span class="sd"> EXIF:ImageDescription (may include template)</span>
<span class="sd"> XMP:Description (may include template)</span> <span class="sd"> XMP:Description (may include template)</span>
<span class="sd"> XMP:Title</span> <span class="sd"> XMP:Title</span>
<span class="sd"> IPTC:ObjectName</span>
<span class="sd"> XMP:TagsList (may include album name, person name, or template)</span> <span class="sd"> XMP:TagsList (may include album name, person name, or template)</span>
<span class="sd"> IPTC:Keywords (may include album name, person name, or template)</span> <span class="sd"> IPTC:Keywords (may include album name, person name, or template)</span>
<span class="sd"> IPTC:Caption-Abstract</span>
<span class="sd"> XMP:Subject (set to keywords + persons)</span> <span class="sd"> XMP:Subject (set to keywords + persons)</span>
<span class="sd"> XMP:PersonInImage</span> <span class="sd"> XMP:PersonInImage</span>
<span class="sd"> EXIF:GPSLatitudeRef, EXIF:GPSLongitudeRef</span> <span class="sd"> EXIF:GPSLatitudeRef, EXIF:GPSLongitudeRef</span>
@@ -1461,6 +1508,9 @@
<span class="sd"> QuickTime:ModifyDate (UTC)</span> <span class="sd"> QuickTime:ModifyDate (UTC)</span>
<span class="sd"> QuickTime:GPSCoordinates</span> <span class="sd"> QuickTime:GPSCoordinates</span>
<span class="sd"> UserData:GPSCoordinates</span> <span class="sd"> UserData:GPSCoordinates</span>
<span class="sd"> Reference: </span>
<span class="sd"> https://iptc.org/std/photometadata/specification/IPTC-PhotoMetadata-201610_1.pdf</span>
<span class="sd"> &quot;&quot;&quot;</span> <span class="sd"> &quot;&quot;&quot;</span>
<span class="n">exif</span> <span class="o">=</span> <span class="p">(</span> <span class="n">exif</span> <span class="o">=</span> <span class="p">(</span>
@@ -1480,30 +1530,34 @@
<span class="n">description</span> <span class="o">=</span> <span class="s2">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">rendered</span><span class="p">)</span> <span class="k">if</span> <span class="n">rendered</span> <span class="k">else</span> <span class="s2">&quot;&quot;</span> <span class="n">description</span> <span class="o">=</span> <span class="s2">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">rendered</span><span class="p">)</span> <span class="k">if</span> <span class="n">rendered</span> <span class="k">else</span> <span class="s2">&quot;&quot;</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;EXIF:ImageDescription&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">description</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;EXIF:ImageDescription&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">description</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;XMP:Description&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">description</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;XMP:Description&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">description</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;IPTC:Caption-Abstract&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">description</span>
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">description</span><span class="p">:</span> <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">description</span><span class="p">:</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;EXIF:ImageDescription&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">description</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;EXIF:ImageDescription&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">description</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;XMP:Description&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">description</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;XMP:Description&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">description</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;IPTC:Caption-Abstract&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">description</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">:</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;XMP:Title&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;XMP:Title&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;IPTC:ObjectName&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span>
<span class="n">keyword_list</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">keyword_list</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">if</span> <span class="n">merge_exif_keywords</span><span class="p">:</span> <span class="k">if</span> <span class="n">merge_exif_keywords</span><span class="p">:</span>
<span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_get_exif_keywords</span><span class="p">())</span> <span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_get_exif_keywords</span><span class="p">())</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">keywords</span><span class="p">:</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">keywords</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">replace_keywords</span><span class="p">:</span>
<span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">keywords</span><span class="p">)</span> <span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">keywords</span><span class="p">)</span>
<span class="n">person_list</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">person_list</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">if</span> <span class="n">merge_exif_persons</span><span class="p">:</span> <span class="k">if</span> <span class="n">persons</span><span class="p">:</span>
<span class="n">person_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_get_exif_persons</span><span class="p">())</span> <span class="k">if</span> <span class="n">merge_exif_persons</span><span class="p">:</span>
<span class="n">person_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_get_exif_persons</span><span class="p">())</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">persons</span><span class="p">:</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">persons</span><span class="p">:</span>
<span class="c1"># filter out _UNKNOWN_PERSON</span> <span class="c1"># filter out _UNKNOWN_PERSON</span>
<span class="n">person_list</span><span class="o">.</span><span class="n">extend</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="bp">self</span><span class="o">.</span><span class="n">persons</span> <span class="k">if</span> <span class="n">p</span> <span class="o">!=</span> <span class="n">_UNKNOWN_PERSON</span><span class="p">])</span> <span class="n">person_list</span><span class="o">.</span><span class="n">extend</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="bp">self</span><span class="o">.</span><span class="n">persons</span> <span class="k">if</span> <span class="n">p</span> <span class="o">!=</span> <span class="n">_UNKNOWN_PERSON</span><span class="p">])</span>
<span class="k">if</span> <span class="n">use_persons_as_keywords</span> <span class="ow">and</span> <span class="n">person_list</span><span class="p">:</span> <span class="k">if</span> <span class="n">use_persons_as_keywords</span> <span class="ow">and</span> <span class="n">person_list</span><span class="p">:</span>
<span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">person_list</span><span class="p">)</span> <span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">person_list</span><span class="p">)</span>
<span class="k">if</span> <span class="n">use_albums_as_keywords</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">albums</span><span class="p">:</span> <span class="k">if</span> <span class="n">use_albums_as_keywords</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">albums</span><span class="p">:</span>
<span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">albums</span><span class="p">)</span> <span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">albums</span><span class="p">)</span>
@@ -1547,25 +1601,26 @@
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;XMP:Subject&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">keyword_list</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;XMP:Subject&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">keyword_list</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;XMP:TagsList&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">keyword_list</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;XMP:TagsList&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">keyword_list</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
<span class="k">if</span> <span class="n">person_list</span><span class="p">:</span> <span class="k">if</span> <span class="n">persons</span> <span class="ow">and</span> <span class="n">person_list</span><span class="p">:</span>
<span class="n">person_list</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">person_list</span><span class="p">)))</span> <span class="n">person_list</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">person_list</span><span class="p">)))</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;XMP:PersonInImage&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">person_list</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;XMP:PersonInImage&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">person_list</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
<span class="c1"># if self.favorite():</span> <span class="c1"># if self.favorite():</span>
<span class="c1"># exif[&quot;Rating&quot;] = 5</span> <span class="c1"># exif[&quot;Rating&quot;] = 5</span>
<span class="p">(</span><span class="n">lat</span><span class="p">,</span> <span class="n">lon</span><span class="p">)</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">location</span> <span class="k">if</span> <span class="n">location</span><span class="p">:</span>
<span class="k">if</span> <span class="n">lat</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">lon</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span> <span class="p">(</span><span class="n">lat</span><span class="p">,</span> <span class="n">lon</span><span class="p">)</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">location</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">isphoto</span><span class="p">:</span> <span class="k">if</span> <span class="n">lat</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">lon</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;EXIF:GPSLatitude&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">lat</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">isphoto</span><span class="p">:</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;EXIF:GPSLongitude&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">lon</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;EXIF:GPSLatitude&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">lat</span>
<span class="n">lat_ref</span> <span class="o">=</span> <span class="s2">&quot;N&quot;</span> <span class="k">if</span> <span class="n">lat</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="k">else</span> <span class="s2">&quot;S&quot;</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;EXIF:GPSLongitude&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">lon</span>
<span class="n">lon_ref</span> <span class="o">=</span> <span class="s2">&quot;E&quot;</span> <span class="k">if</span> <span class="n">lon</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="k">else</span> <span class="s2">&quot;W&quot;</span> <span class="n">lat_ref</span> <span class="o">=</span> <span class="s2">&quot;N&quot;</span> <span class="k">if</span> <span class="n">lat</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="k">else</span> <span class="s2">&quot;S&quot;</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;EXIF:GPSLatitudeRef&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">lat_ref</span> <span class="n">lon_ref</span> <span class="o">=</span> <span class="s2">&quot;E&quot;</span> <span class="k">if</span> <span class="n">lon</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="k">else</span> <span class="s2">&quot;W&quot;</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;EXIF:GPSLongitudeRef&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">lon_ref</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;EXIF:GPSLatitudeRef&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">lat_ref</span>
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">ismovie</span><span class="p">:</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;EXIF:GPSLongitudeRef&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">lon_ref</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;Keys:GPSCoordinates&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">lat</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">lon</span><span class="si">}</span><span class="s2">&quot;</span> <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">ismovie</span><span class="p">:</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;UserData:GPSCoordinates&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">lat</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">lon</span><span class="si">}</span><span class="s2">&quot;</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;Keys:GPSCoordinates&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">lat</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">lon</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;UserData:GPSCoordinates&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">lat</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">lon</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="c1"># process date/time and timezone offset</span> <span class="c1"># process date/time and timezone offset</span>
<span class="c1"># Photos exports the following fields and sets modify date to creation date</span> <span class="c1"># Photos exports the following fields and sets modify date to creation date</span>
@@ -1624,6 +1679,13 @@
<span class="n">exif</span><span class="p">[</span><span class="s2">&quot;QuickTime:ModifyDate&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">datetime_tz_to_utc</span><span class="p">(</span> <span class="n">exif</span><span class="p">[</span><span class="s2">&quot;QuickTime:ModifyDate&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">datetime_tz_to_utc</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">date_modified</span> <span class="bp">self</span><span class="o">.</span><span class="n">date_modified</span>
<span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&quot;%Y:%m:</span><span class="si">%d</span><span class="s2"> %H:%M:%S&quot;</span><span class="p">)</span> <span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&quot;%Y:%m:</span><span class="si">%d</span><span class="s2"> %H:%M:%S&quot;</span><span class="p">)</span>
<span class="c1"># remove any new lines in any fields</span>
<span class="k">for</span> <span class="n">field</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">exif</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">val</span><span class="p">)</span> <span class="o">==</span> <span class="nb">str</span><span class="p">:</span>
<span class="n">exif</span><span class="p">[</span><span class="n">field</span><span class="p">]</span> <span class="o">=</span> <span class="n">val</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="s2">&quot; &quot;</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">type</span><span class="p">(</span><span class="n">val</span><span class="p">)</span> <span class="o">==</span> <span class="nb">list</span><span class="p">:</span>
<span class="n">exif</span><span class="p">[</span><span class="n">field</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="s2">&quot; &quot;</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">val</span><span class="p">]</span>
<span class="k">return</span> <span class="n">exif</span> <span class="k">return</span> <span class="n">exif</span>
@@ -1673,6 +1735,9 @@
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">filename</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="p">):</span> <span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Return dict of EXIF details for building exiftool JSON sidecar or sending commands to ExifTool.</span> <span class="sd">&quot;&quot;&quot;Return dict of EXIF details for building exiftool JSON sidecar or sending commands to ExifTool.</span>
<span class="sd"> Does not include all the EXIF fields as those are likely already in the image.</span> <span class="sd"> Does not include all the EXIF fields as those are likely already in the image.</span>
@@ -1687,13 +1752,18 @@
<span class="sd"> merge_exif_keywords: boolean; if True, merged keywords found in file&#39;s exif data (requires exiftool)</span> <span class="sd"> merge_exif_keywords: boolean; if True, merged keywords found in file&#39;s exif data (requires exiftool)</span>
<span class="sd"> merge_exif_persons: boolean; if True, merged persons found in file&#39;s exif data (requires exiftool)</span> <span class="sd"> merge_exif_persons: boolean; if True, merged persons found in file&#39;s exif data (requires exiftool)</span>
<span class="sd"> filename: filename of the destination image file for including in exiftool signature in JSON sidecar</span> <span class="sd"> filename: filename of the destination image file for including in exiftool signature in JSON sidecar</span>
<span class="sd"> persons: if True, include person data</span>
<span class="sd"> location: if True, include location data</span>
<span class="sd"> replace_keywords: if True, keyword_template replaces any keywords, otherwise it&#39;s additive</span>
<span class="sd"> Returns: dict with exiftool tags / values</span> <span class="sd"> Returns: dict with exiftool tags / values</span>
<span class="sd"> Exports the following:</span> <span class="sd"> Exports the following:</span>
<span class="sd"> EXIF:ImageDescription</span> <span class="sd"> EXIF:ImageDescription</span>
<span class="sd"> XMP:Description (may include template)</span> <span class="sd"> XMP:Description (may include template)</span>
<span class="sd"> IPTC:CaptionAbstract</span>
<span class="sd"> XMP:Title</span> <span class="sd"> XMP:Title</span>
<span class="sd"> IPTC:ObjectName</span>
<span class="sd"> XMP:TagsList</span> <span class="sd"> XMP:TagsList</span>
<span class="sd"> IPTC:Keywords (may include album name, person name, or template)</span> <span class="sd"> IPTC:Keywords (may include album name, person name, or template)</span>
<span class="sd"> XMP:Subject (set to keywords + person)</span> <span class="sd"> XMP:Subject (set to keywords + person)</span>
@@ -1721,6 +1791,9 @@
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="n">merge_exif_keywords</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="n">merge_exif_persons</span><span class="p">,</span>
<span class="n">filename</span><span class="o">=</span><span class="n">filename</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="n">filename</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="n">persons</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="n">location</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="n">replace_keywords</span><span class="p">,</span>
<span class="p">)</span> <span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">tag_groups</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">tag_groups</span><span class="p">:</span>
@@ -1743,6 +1816,9 @@
<span class="n">extension</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">extension</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">merge_exif_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">merge_exif_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">merge_exif_persons</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">merge_exif_persons</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">persons</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">replace_keywords</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="p">):</span> <span class="p">):</span>
<span class="sd">&quot;&quot;&quot;returns string for XMP sidecar</span> <span class="sd">&quot;&quot;&quot;returns string for XMP sidecar</span>
<span class="sd"> use_albums_as_keywords: treat album names as keywords</span> <span class="sd"> use_albums_as_keywords: treat album names as keywords</span>
@@ -1752,6 +1828,9 @@
<span class="sd"> extension: which extension to use for SidecarForExtension property</span> <span class="sd"> extension: which extension to use for SidecarForExtension property</span>
<span class="sd"> merge_exif_keywords: boolean; if True, merged keywords found in file&#39;s exif data (requires exiftool)</span> <span class="sd"> merge_exif_keywords: boolean; if True, merged keywords found in file&#39;s exif data (requires exiftool)</span>
<span class="sd"> merge_exif_persons: boolean; if True, merged persons found in file&#39;s exif data (requires exiftool)</span> <span class="sd"> merge_exif_persons: boolean; if True, merged persons found in file&#39;s exif data (requires exiftool)</span>
<span class="sd"> persons: if True, include person data</span>
<span class="sd"> location: if True, include location data</span>
<span class="sd"> replace_keywords: if True, keyword_template replaces any keywords, otherwise it&#39;s additive</span>
<span class="sd"> &quot;&quot;&quot;</span> <span class="sd"> &quot;&quot;&quot;</span>
<span class="n">xmp_template_file</span> <span class="o">=</span> <span class="p">(</span> <span class="n">xmp_template_file</span> <span class="o">=</span> <span class="p">(</span>
@@ -1775,22 +1854,23 @@
<span class="k">if</span> <span class="n">merge_exif_keywords</span><span class="p">:</span> <span class="k">if</span> <span class="n">merge_exif_keywords</span><span class="p">:</span>
<span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_get_exif_keywords</span><span class="p">())</span> <span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_get_exif_keywords</span><span class="p">())</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">keywords</span><span class="p">:</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">keywords</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">replace_keywords</span><span class="p">:</span>
<span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">keywords</span><span class="p">)</span> <span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">keywords</span><span class="p">)</span>
<span class="c1"># TODO: keyword handling in this and _exiftool_json_sidecar is</span> <span class="c1"># TODO: keyword handling in this and _exiftool_json_sidecar is</span>
<span class="c1"># good candidate for pulling out in a function</span> <span class="c1"># good candidate for pulling out in a function</span>
<span class="n">person_list</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">person_list</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">if</span> <span class="n">merge_exif_persons</span><span class="p">:</span> <span class="k">if</span> <span class="n">persons</span><span class="p">:</span>
<span class="n">person_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_get_exif_persons</span><span class="p">())</span> <span class="k">if</span> <span class="n">merge_exif_persons</span><span class="p">:</span>
<span class="n">person_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_get_exif_persons</span><span class="p">())</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">persons</span><span class="p">:</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">persons</span><span class="p">:</span>
<span class="c1"># filter out _UNKNOWN_PERSON</span> <span class="c1"># filter out _UNKNOWN_PERSON</span>
<span class="n">person_list</span><span class="o">.</span><span class="n">extend</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="bp">self</span><span class="o">.</span><span class="n">persons</span> <span class="k">if</span> <span class="n">p</span> <span class="o">!=</span> <span class="n">_UNKNOWN_PERSON</span><span class="p">])</span> <span class="n">person_list</span><span class="o">.</span><span class="n">extend</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="bp">self</span><span class="o">.</span><span class="n">persons</span> <span class="k">if</span> <span class="n">p</span> <span class="o">!=</span> <span class="n">_UNKNOWN_PERSON</span><span class="p">])</span>
<span class="k">if</span> <span class="n">use_persons_as_keywords</span> <span class="ow">and</span> <span class="n">person_list</span><span class="p">:</span> <span class="k">if</span> <span class="n">use_persons_as_keywords</span> <span class="ow">and</span> <span class="n">person_list</span><span class="p">:</span>
<span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">person_list</span><span class="p">)</span> <span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">person_list</span><span class="p">)</span>
<span class="k">if</span> <span class="n">use_albums_as_keywords</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">albums</span><span class="p">:</span> <span class="k">if</span> <span class="n">use_albums_as_keywords</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">albums</span><span class="p">:</span>
<span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">albums</span><span class="p">)</span> <span class="n">keyword_list</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">albums</span><span class="p">)</span>
@@ -1820,11 +1900,14 @@
<span class="c1"># sorted mainly to make testing the XMP file easier</span> <span class="c1"># sorted mainly to make testing the XMP file easier</span>
<span class="k">if</span> <span class="n">keyword_list</span><span class="p">:</span> <span class="k">if</span> <span class="n">keyword_list</span><span class="p">:</span>
<span class="n">keyword_list</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">keyword_list</span><span class="p">)))</span> <span class="n">keyword_list</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">keyword_list</span><span class="p">)))</span>
<span class="k">if</span> <span class="n">person_list</span><span class="p">:</span> <span class="k">if</span> <span class="n">persons</span> <span class="ow">and</span> <span class="n">person_list</span><span class="p">:</span>
<span class="n">person_list</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">person_list</span><span class="p">)))</span> <span class="n">person_list</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">person_list</span><span class="p">)))</span>
<span class="n">subject_list</span> <span class="o">=</span> <span class="n">keyword_list</span> <span class="n">subject_list</span> <span class="o">=</span> <span class="n">keyword_list</span>
<span class="k">if</span> <span class="n">location</span><span class="p">:</span>
<span class="n">latlon</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">location</span>
<span class="n">xmp_str</span> <span class="o">=</span> <span class="n">xmp_template</span><span class="o">.</span><span class="n">render</span><span class="p">(</span> <span class="n">xmp_str</span> <span class="o">=</span> <span class="n">xmp_template</span><span class="o">.</span><span class="n">render</span><span class="p">(</span>
<span class="n">photo</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span> <span class="n">photo</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span>
<span class="n">description</span><span class="o">=</span><span class="n">description</span><span class="p">,</span> <span class="n">description</span><span class="o">=</span><span class="n">description</span><span class="p">,</span>
@@ -1832,6 +1915,7 @@
<span class="n">persons</span><span class="o">=</span><span class="n">person_list</span><span class="p">,</span> <span class="n">persons</span><span class="o">=</span><span class="n">person_list</span><span class="p">,</span>
<span class="n">subjects</span><span class="o">=</span><span class="n">subject_list</span><span class="p">,</span> <span class="n">subjects</span><span class="o">=</span><span class="n">subject_list</span><span class="p">,</span>
<span class="n">extension</span><span class="o">=</span><span class="n">extension</span><span class="p">,</span> <span class="n">extension</span><span class="o">=</span><span class="n">extension</span><span class="p">,</span>
<span class="n">location</span><span class="o">=</span><span class="n">latlon</span><span class="p">,</span>
<span class="n">version</span><span class="o">=</span><span class="n">__version__</span><span class="p">,</span> <span class="n">version</span><span class="o">=</span><span class="n">__version__</span><span class="p">,</span>
<span class="p">)</span> <span class="p">)</span>
@@ -1912,7 +1996,7 @@
&copy;2021, Rhet Turnbull. &copy;2021, Rhet Turnbull.
| |
Powered by <a href="http://sphinx-doc.org/">Sphinx 3.4.3</a> Powered by <a href="http://sphinx-doc.org/">Sphinx 3.5.2</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a> &amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
</div> </div>

View File

@@ -29,9 +29,14 @@ if (!window.console || !console.firebug) {
/** /**
* small helper function to urldecode strings * small helper function to urldecode strings
*
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
*/ */
jQuery.urldecode = function(x) { jQuery.urldecode = function(x) {
return decodeURIComponent(x).replace(/\+/g, ' '); if (!x) {
return x
}
return decodeURIComponent(x.replace(/\+/g, ' '));
}; };
/** /**

View File

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

View File

@@ -13,7 +13,8 @@
var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]; var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
/* Non-minified version JS is _stemmer.js if file is provided */ /* Non-minified version is copied as a separate JS file, is available */
/** /**
* Porter Stemmer * Porter Stemmer
*/ */
@@ -199,7 +200,6 @@ var Stemmer = function() {
var splitChars = (function() { var splitChars = (function() {
var result = {}; var result = {};
var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648, var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648,

View File

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

View File

@@ -248,7 +248,7 @@ var Search = {
// results left, load the summary and display it // results left, load the summary and display it
if (results.length) { if (results.length) {
var item = results.pop(); var item = results.pop();
var listItem = $('<li style="display:none"></li>'); var listItem = $('<li></li>');
var requestUrl = ""; var requestUrl = "";
var linkUrl = ""; var linkUrl = "";
if (DOCUMENTATION_OPTIONS.BUILDER === 'dirhtml') { if (DOCUMENTATION_OPTIONS.BUILDER === 'dirhtml') {
@@ -273,9 +273,9 @@ var Search = {
if (item[3]) { if (item[3]) {
listItem.append($('<span> (' + item[3] + ')</span>')); listItem.append($('<span> (' + item[3] + ')</span>'));
Search.output.append(listItem); Search.output.append(listItem);
listItem.slideDown(5, function() { setTimeout(function() {
displayNextItem(); displayNextItem();
}); }, 5);
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) { } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
$.ajax({url: requestUrl, $.ajax({url: requestUrl,
dataType: "text", dataType: "text",
@@ -285,16 +285,16 @@ var Search = {
listItem.append(Search.makeSearchSummary(data, searchterms, hlterms)); listItem.append(Search.makeSearchSummary(data, searchterms, hlterms));
} }
Search.output.append(listItem); Search.output.append(listItem);
listItem.slideDown(5, function() { setTimeout(function() {
displayNextItem(); displayNextItem();
}); }, 5);
}}); }});
} else { } else {
// no source available, just display title // no source available, just display title
Search.output.append(listItem); Search.output.append(listItem);
listItem.slideDown(5, function() { setTimeout(function() {
displayNextItem(); displayNextItem();
}); }, 5);
} }
} }
// search finished, update title and status message // search finished, update title and status message
@@ -379,6 +379,13 @@ var Search = {
return results; return results;
}, },
/**
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
*/
escapeRegExp : function(string) {
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
},
/** /**
* search for full-text terms in the index * search for full-text terms in the index
*/ */
@@ -402,13 +409,14 @@ var Search = {
]; ];
// add support for partial matches // add support for partial matches
if (word.length > 2) { if (word.length > 2) {
var word_regex = this.escapeRegExp(word);
for (var w in terms) { for (var w in terms) {
if (w.match(word) && !terms[word]) { if (w.match(word_regex) && !terms[word]) {
_o.push({files: terms[w], score: Scorer.partialTerm}) _o.push({files: terms[w], score: Scorer.partialTerm})
} }
} }
for (var w in titleterms) { for (var w in titleterms) {
if (w.match(word) && !titleterms[word]) { if (w.match(word_regex) && !titleterms[word]) {
_o.push({files: titleterms[w], score: Scorer.partialTitle}) _o.push({files: titleterms[w], score: Scorer.partialTitle})
} }
} }

2027
docs/_static/underscore-1.12.0.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Index &#8212; osxphotos 0.41.0 documentation</title> <title>Index &#8212; osxphotos 0.41.2 documentation</title>
<link rel="stylesheet" href="_static/pygments.css" type="text/css" /> <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/alabaster.css" type="text/css" /> <link rel="stylesheet" href="_static/alabaster.css" type="text/css" />
<script id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> <script id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
@@ -776,6 +776,13 @@
<li><a href="cli.html#cmdoption-osxphotos-export-portrait">osxphotos-export command line option</a> <li><a href="cli.html#cmdoption-osxphotos-export-portrait">osxphotos-export command line option</a>
</li> </li>
<li><a href="cli.html#cmdoption-osxphotos-query-portrait">osxphotos-query command line option</a> <li><a href="cli.html#cmdoption-osxphotos-query-portrait">osxphotos-query command line option</a>
</li>
</ul></li>
<li>
--replace-keywords
<ul>
<li><a href="cli.html#cmdoption-osxphotos-export-replace-keywords">osxphotos-export command line option</a>
</li> </li>
</ul></li> </ul></li>
<li> <li>
@@ -1017,6 +1024,8 @@
<table style="width: 100%" class="indextable genindextable"><tr> <table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul> <td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#osxphotos.PhotoInfo.SearchInfo.activities">activities() (osxphotos.PhotoInfo.SearchInfo property)</a> <li><a href="reference.html#osxphotos.PhotoInfo.SearchInfo.activities">activities() (osxphotos.PhotoInfo.SearchInfo property)</a>
</li>
<li><a href="reference.html#osxphotos.PhotoInfo.adjustments">adjustments() (osxphotos.PhotoInfo property)</a>
</li> </li>
<li><a href="reference.html#osxphotos.PhotoInfo.album_info">album_info() (osxphotos.PhotoInfo property)</a> <li><a href="reference.html#osxphotos.PhotoInfo.album_info">album_info() (osxphotos.PhotoInfo property)</a>
@@ -1032,10 +1041,10 @@
<li><a href="reference.html#osxphotos.PhotosDB.albums">(osxphotos.PhotosDB property)</a> <li><a href="reference.html#osxphotos.PhotosDB.albums">(osxphotos.PhotosDB property)</a>
</li> </li>
</ul></li> </ul></li>
<li><a href="reference.html#osxphotos.PhotosDB.albums_as_dict">albums_as_dict() (osxphotos.PhotosDB property)</a>
</li>
</ul></td> </ul></td>
<td style="width: 33%; vertical-align: top;"><ul> <td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#osxphotos.PhotosDB.albums_as_dict">albums_as_dict() (osxphotos.PhotosDB property)</a>
</li>
<li><a href="reference.html#osxphotos.PhotosDB.albums_shared">albums_shared() (osxphotos.PhotosDB property)</a> <li><a href="reference.html#osxphotos.PhotosDB.albums_shared">albums_shared() (osxphotos.PhotosDB property)</a>
</li> </li>
<li><a href="reference.html#osxphotos.PhotosDB.albums_shared_as_dict">albums_shared_as_dict() (osxphotos.PhotosDB property)</a> <li><a href="reference.html#osxphotos.PhotosDB.albums_shared_as_dict">albums_shared_as_dict() (osxphotos.PhotosDB property)</a>
@@ -1553,6 +1562,8 @@
<li><a href="cli.html#cmdoption-osxphotos-export-place">--place &lt;PLACE&gt;</a> <li><a href="cli.html#cmdoption-osxphotos-export-place">--place &lt;PLACE&gt;</a>
</li> </li>
<li><a href="cli.html#cmdoption-osxphotos-export-portrait">--portrait</a> <li><a href="cli.html#cmdoption-osxphotos-export-portrait">--portrait</a>
</li>
<li><a href="cli.html#cmdoption-osxphotos-export-replace-keywords">--replace-keywords</a>
</li> </li>
<li><a href="cli.html#cmdoption-osxphotos-export-report">--report &lt;path to export report&gt;</a> <li><a href="cli.html#cmdoption-osxphotos-export-report">--report &lt;path to export report&gt;</a>
</li> </li>
@@ -2108,7 +2119,7 @@
&copy;2021, Rhet Turnbull. &copy;2021, Rhet Turnbull.
| |
Powered by <a href="http://sphinx-doc.org/">Sphinx 3.4.3</a> Powered by <a href="http://sphinx-doc.org/">Sphinx 3.5.2</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a> &amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
</div> </div>

View File

@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Welcome to osxphotoss documentation! &#8212; osxphotos 0.41.0 documentation</title> <title>Welcome to osxphotoss documentation! &#8212; osxphotos 0.41.2 documentation</title>
<link rel="stylesheet" href="_static/pygments.css" type="text/css" /> <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/alabaster.css" type="text/css" /> <link rel="stylesheet" href="_static/alabaster.css" type="text/css" />
<script id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> <script id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
@@ -365,7 +365,7 @@ Alternatively, you can also run the command line utility like this: <code class=
&copy;2021, Rhet Turnbull. &copy;2021, Rhet Turnbull.
| |
Powered by <a href="http://sphinx-doc.org/">Sphinx 3.4.3</a> Powered by <a href="http://sphinx-doc.org/">Sphinx 3.5.2</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a> &amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
| |

View File

@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>osxphotos &#8212; osxphotos 0.41.0 documentation</title> <title>osxphotos &#8212; osxphotos 0.41.2 documentation</title>
<link rel="stylesheet" href="_static/pygments.css" type="text/css" /> <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/alabaster.css" type="text/css" /> <link rel="stylesheet" href="_static/alabaster.css" type="text/css" />
<script id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> <script id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
@@ -91,7 +91,7 @@
&copy;2021, Rhet Turnbull. &copy;2021, Rhet Turnbull.
| |
Powered by <a href="http://sphinx-doc.org/">Sphinx 3.4.3</a> Powered by <a href="http://sphinx-doc.org/">Sphinx 3.5.2</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a> &amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
| |

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,3 @@
""" version info """ """ version info """
__version__ = "0.41.2" __version__ = "0.41.3"

View File

@@ -782,7 +782,10 @@ def cli(ctx, db, json_, debug):
"--cleanup", "--cleanup",
is_flag=True, is_flag=True,
help="Cleanup export directory by deleting any files which were not included in this export set. " help="Cleanup export directory by deleting any files which were not included in this export set. "
"For example, photos which had previously been exported and were subsequently deleted in Photos.", "For example, photos which had previously been exported and were subsequently deleted in Photos. "
"WARNING: --cleanup will delete *any* files in the export directory that were not exported by osxphotos, "
"for example, your own scripts or other files. Be sure this is what you intend before using "
"--cleanup. Use --dry-run with --cleanup first if you're not certain.",
) )
@click.option( @click.option(
"--exportdb", "--exportdb",
@@ -1506,10 +1509,14 @@ def export(
+ [str(pathlib.Path(export_db_path).resolve())] + [str(pathlib.Path(export_db_path).resolve())]
) )
click.echo(f"Cleaning up {dest}") click.echo(f"Cleaning up {dest}")
(cleaned_files, cleaned_dirs) = cleanup_files(dest, all_files, fileutil) cleaned_files, cleaned_dirs = cleanup_files(dest, all_files, fileutil)
file_str = "files" if cleaned_files != 1 else "file" file_str = "files" if len(cleaned_files) != 1 else "file"
dir_str = "directories" if cleaned_dirs != 1 else "directory" dir_str = "directories" if len(cleaned_dirs) != 1 else "directory"
click.echo(f"Deleted: {cleaned_files} {file_str}, {cleaned_dirs} {dir_str}") click.echo(
f"Deleted: {len(cleaned_files)} {file_str}, {len(cleaned_dirs)} {dir_str}"
)
results.deleted_files = cleaned_files
results.deleted_directories = cleaned_dirs
if report: if report:
verbose_(f"Writing export report to {report}") verbose_(f"Writing export report to {report}")
@@ -2893,8 +2900,12 @@ def write_export_report(report_file, results):
"exiftool_error": "", "exiftool_error": "",
"extended_attributes_written": 0, "extended_attributes_written": 0,
"extended_attributes_skipped": 0, "extended_attributes_skipped": 0,
"cleanup_deleted_file": 0,
"cleanup_deleted_directory": 0,
} }
for result in results.all_files() for result in results.all_files()
+ results.deleted_files
+ results.deleted_directories
} }
for result in results.exported: for result in results.exported:
@@ -2960,6 +2971,12 @@ def write_export_report(report_file, results):
for result in results.xattr_skipped: for result in results.xattr_skipped:
all_results[result]["extended_attributes_skipped"] = 1 all_results[result]["extended_attributes_skipped"] = 1
for result in results.deleted_files:
all_results[result]["cleanup_deleted_file"] = 1
for result in results.deleted_directories:
all_results[result]["cleanup_deleted_directory"] = 1
report_columns = [ report_columns = [
"filename", "filename",
"exported", "exported",
@@ -2978,6 +2995,8 @@ def write_export_report(report_file, results):
"exiftool_error", "exiftool_error",
"extended_attributes_written", "extended_attributes_written",
"extended_attributes_skipped", "extended_attributes_skipped",
"cleanup_deleted_file",
"cleanup_deleted_directory",
] ]
try: try:
@@ -3004,27 +3023,27 @@ def cleanup_files(dest_path, files_to_keep, fileutil):
fileutile: FileUtil object fileutile: FileUtil object
Returns: Returns:
tuple of (number of files deleted, number of directories deleted) tuple of (list of files deleted, list of directories deleted)
""" """
keepers = {str(filename).lower(): 1 for filename in files_to_keep} keepers = {str(filename).lower(): 1 for filename in files_to_keep}
deleted_files = 0 deleted_files = []
for p in pathlib.Path(dest_path).rglob("*"): for p in pathlib.Path(dest_path).rglob("*"):
path = str(p).lower() path = str(p).lower()
if p.is_file() and path not in keepers: if p.is_file() and path not in keepers:
verbose_(f"Deleting {p}") verbose_(f"Deleting {p}")
fileutil.unlink(p) fileutil.unlink(p)
deleted_files += 1 deleted_files.append(str(p))
# delete empty directories # delete empty directories
deleted_dirs = 0 deleted_dirs = []
for p in pathlib.Path(dest_path).rglob("*"): for p in pathlib.Path(dest_path).rglob("*"):
path = str(p).lower() path = str(p).lower()
# if directory and directory is empty # if directory and directory is empty
if p.is_dir() and not next(p.iterdir(), False): if p.is_dir() and not next(p.iterdir(), False):
verbose_(f"Deleting empty directory {p}") verbose_(f"Deleting empty directory {p}")
fileutil.rmdir(p) fileutil.rmdir(p)
deleted_dirs += 1 deleted_dirs.append(str(p))
return (deleted_files, deleted_dirs) return (deleted_files, deleted_dirs)

View File

@@ -87,6 +87,8 @@ class ExportResults:
exiftool_error=None, exiftool_error=None,
xattr_written=None, xattr_written=None,
xattr_skipped=None, xattr_skipped=None,
deleted_files=None,
deleted_directories=None,
): ):
self.exported = exported or [] self.exported = exported or []
self.new = new or [] self.new = new or []
@@ -107,6 +109,8 @@ class ExportResults:
self.exiftool_error = exiftool_error or [] self.exiftool_error = exiftool_error or []
self.xattr_written = xattr_written or [] self.xattr_written = xattr_written or []
self.xattr_skipped = xattr_skipped or [] self.xattr_skipped = xattr_skipped or []
self.deleted_files = deleted_files or []
self.deleted_directories = deleted_directories or []
def all_files(self): def all_files(self):
""" return all filenames contained in results """ """ return all filenames contained in results """
@@ -151,6 +155,8 @@ class ExportResults:
self.error += other.error self.error += other.error
self.exiftool_warning += other.exiftool_warning self.exiftool_warning += other.exiftool_warning
self.exiftool_error += other.exiftool_error self.exiftool_error += other.exiftool_error
self.deleted_files += other.deleted_files
self.deleted_directories += other.deleted_directories
return self return self
def __str__(self): def __str__(self):
@@ -173,6 +179,8 @@ class ExportResults:
+ f",error={self.error}" + f",error={self.error}"
+ f",exiftool_warning={self.exiftool_warning}" + f",exiftool_warning={self.exiftool_warning}"
+ f",exiftool_error={self.exiftool_error}" + f",exiftool_error={self.exiftool_error}"
+ f",deleted_files={self.deleted_files}"
+ f",deleted_directories={self.deleted_directories}"
+ ")" + ")"
) )
@@ -613,9 +621,9 @@ def export2(
) )
edited_name = pathlib.Path(self.path_edited).name edited_name = pathlib.Path(self.path_edited).name
edited_suffix = pathlib.Path(edited_name).suffix edited_suffix = pathlib.Path(edited_name).suffix
fname = pathlib.Path(self.filename).stem + edited_identifier + edited_suffix fname = pathlib.Path(self.original_filename).stem + edited_identifier + edited_suffix
else: else:
fname = self.filename fname = self.original_filename
uti = self.uti if edited else self.uti_original uti = self.uti if edited else self.uti_original
if convert_to_jpeg and self.isphoto and uti != "public.jpeg": if convert_to_jpeg and self.isphoto and uti != "public.jpeg":

File diff suppressed because one or more lines are too long

View File

@@ -731,7 +731,7 @@ def test_export_1():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -776,7 +776,7 @@ def test_export_3():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
filename2 = pathlib.Path(filename) filename2 = pathlib.Path(filename)
filename2 = f"{filename2.stem} (1){filename2.suffix}" filename2 = f"{filename2.stem} (1){filename2.suffix}"
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
@@ -829,7 +829,7 @@ def test_export_5():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -994,7 +994,7 @@ def test_export_12():
edited_name = pathlib.Path(photos[0].path_edited).name edited_name = pathlib.Path(photos[0].path_edited).name
edited_suffix = pathlib.Path(edited_name).suffix edited_suffix = pathlib.Path(edited_name).suffix
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix filename = pathlib.Path(photos[0].original_filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True)[0] got_dest = photos[0].export(dest, edited=True)[0]

View File

@@ -618,7 +618,7 @@ def test_export_1(photosdb):
dest = tempdir.name dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -657,7 +657,7 @@ def test_export_3(photosdb):
dest = tempdir.name dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
filename2 = pathlib.Path(filename) filename2 = pathlib.Path(filename)
filename2 = f"{filename2.stem} (1){filename2.suffix}" filename2 = f"{filename2.stem} (1){filename2.suffix}"
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
@@ -704,7 +704,7 @@ def test_export_5(photosdb):
dest = tempdir.name dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -848,7 +848,7 @@ def test_export_12(photosdb):
edited_name = pathlib.Path(photos[0].path_edited).name edited_name = pathlib.Path(photos[0].path_edited).name
edited_suffix = pathlib.Path(edited_name).suffix edited_suffix = pathlib.Path(edited_name).suffix
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix filename = pathlib.Path(photos[0].original_filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True)[0] got_dest = photos[0].export(dest, edited=True)[0]

View File

@@ -418,7 +418,7 @@ def test_export_1():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -463,7 +463,7 @@ def test_export_3():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
filename2 = pathlib.Path(filename) filename2 = pathlib.Path(filename)
filename2 = f"{filename2.stem} (1){filename2.suffix}" filename2 = f"{filename2.stem} (1){filename2.suffix}"
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
@@ -516,7 +516,7 @@ def test_export_5():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -681,7 +681,7 @@ def test_export_12():
edited_name = pathlib.Path(photos[0].path_edited).name edited_name = pathlib.Path(photos[0].path_edited).name
edited_suffix = pathlib.Path(edited_name).suffix edited_suffix = pathlib.Path(edited_name).suffix
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix filename = pathlib.Path(photos[0].original_filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True)[0] got_dest = photos[0].export(dest, edited=True)[0]

View File

@@ -426,7 +426,7 @@ def test_export_1():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -471,7 +471,7 @@ def test_export_3():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
filename2 = pathlib.Path(filename) filename2 = pathlib.Path(filename)
filename2 = f"{filename2.stem} (1){filename2.suffix}" filename2 = f"{filename2.stem} (1){filename2.suffix}"
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
@@ -524,7 +524,7 @@ def test_export_5():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -689,7 +689,7 @@ def test_export_12():
edited_name = pathlib.Path(photos[0].path_edited).name edited_name = pathlib.Path(photos[0].path_edited).name
edited_suffix = pathlib.Path(edited_name).suffix edited_suffix = pathlib.Path(edited_name).suffix
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix filename = pathlib.Path(photos[0].original_filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True)[0] got_dest = photos[0].export(dest, edited=True)[0]

View File

@@ -640,7 +640,7 @@ def test_export_1():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -685,7 +685,7 @@ def test_export_3():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
filename2 = pathlib.Path(filename) filename2 = pathlib.Path(filename)
filename2 = f"{filename2.stem} (1){filename2.suffix}" filename2 = f"{filename2.stem} (1){filename2.suffix}"
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
@@ -738,7 +738,7 @@ def test_export_5():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -903,7 +903,7 @@ def test_export_12():
edited_name = pathlib.Path(photos[0].path_edited).name edited_name = pathlib.Path(photos[0].path_edited).name
edited_suffix = pathlib.Path(edited_name).suffix edited_suffix = pathlib.Path(edited_name).suffix
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix filename = pathlib.Path(photos[0].original_filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True)[0] got_dest = photos[0].export(dest, edited=True)[0]

View File

@@ -635,7 +635,7 @@ def test_export_1(photosdb):
dest = tempdir.name dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -666,7 +666,7 @@ def test_export_3(photosdb):
dest = tempdir.name dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
filename2 = pathlib.Path(filename) filename2 = pathlib.Path(filename)
filename2 = f"{filename2.stem} (1){filename2.suffix}" filename2 = f"{filename2.stem} (1){filename2.suffix}"
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
@@ -705,7 +705,7 @@ def test_export_5(photosdb):
dest = tempdir.name dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -823,7 +823,7 @@ def test_export_12(photosdb):
edited_name = pathlib.Path(photos[0].path_edited).name edited_name = pathlib.Path(photos[0].path_edited).name
edited_suffix = pathlib.Path(edited_name).suffix edited_suffix = pathlib.Path(edited_name).suffix
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix filename = pathlib.Path(photos[0].original_filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True)[0] got_dest = photos[0].export(dest, edited=True)[0]

View File

@@ -702,7 +702,7 @@ def test_export_1(photosdb):
dest = tempdir.name dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -733,7 +733,7 @@ def test_export_3(photosdb):
dest = tempdir.name dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
filename2 = pathlib.Path(filename) filename2 = pathlib.Path(filename)
filename2 = f"{filename2.stem} (1){filename2.suffix}" filename2 = f"{filename2.stem} (1){filename2.suffix}"
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
@@ -772,7 +772,7 @@ def test_export_5(photosdb):
dest = tempdir.name dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -890,7 +890,7 @@ def test_export_12(photosdb):
edited_name = pathlib.Path(photos[0].path_edited).name edited_name = pathlib.Path(photos[0].path_edited).name
edited_suffix = pathlib.Path(edited_name).suffix edited_suffix = pathlib.Path(edited_name).suffix
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix filename = pathlib.Path(photos[0].original_filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True)[0] got_dest = photos[0].export(dest, edited=True)[0]

View File

@@ -95,7 +95,7 @@ def test_export_1(photosdb):
dest = tempdir.name dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -134,7 +134,7 @@ def test_export_3(photosdb):
dest = tempdir.name dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
filename2 = pathlib.Path(filename) filename2 = pathlib.Path(filename)
filename2 = f"{filename2.stem} (1){filename2.suffix}" filename2 = f"{filename2.stem} (1){filename2.suffix}"
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
@@ -181,7 +181,7 @@ def test_export_5(photosdb):
dest = tempdir.name dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
@@ -326,7 +326,7 @@ def test_export_12(photosdb):
edited_name = pathlib.Path(photos[0].path_edited).name edited_name = pathlib.Path(photos[0].path_edited).name
edited_suffix = pathlib.Path(edited_name).suffix edited_suffix = pathlib.Path(edited_name).suffix
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix filename = pathlib.Path(photos[0].original_filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True)[0] got_dest = photos[0].export(dest, edited=True)[0]

View File

@@ -29,7 +29,7 @@ def test_export_default_name(photosdb):
# test basic export # test basic export
# get an unedited image and export it using default filename # get an unedited image and export it using default filename
import os import os
import os.path import pathlib
import tempfile import tempfile
import osxphotos import osxphotos
@@ -38,11 +38,12 @@ def test_export_default_name(photosdb):
dest = tempdir.name dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = pathlib.Path(dest) / filename
expected_dest = expected_dest.parent / f"{expected_dest.stem}.jpeg"
got_dest = photos[0].export(dest, use_photos_export=True)[0] got_dest = photos[0].export(dest, use_photos_export=True)[0]
assert got_dest == expected_dest assert got_dest == str(expected_dest)
assert os.path.isfile(got_dest) assert os.path.isfile(got_dest)
@@ -82,7 +83,7 @@ def test_export_edited(photosdb):
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
suffix = pathlib.Path(photos[0].path_edited).suffix suffix = pathlib.Path(photos[0].path_edited).suffix
filename = f"{pathlib.Path(photos[0].filename).stem}_edited{suffix}" filename = f"{pathlib.Path(photos[0].original_filename).stem}_edited{suffix}"
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, use_photos_export=True, edited=True)[0] got_dest = photos[0].export(dest, use_photos_export=True, edited=True)[0]

View File

@@ -16,14 +16,14 @@ UUID_DICT = {
} }
NAMES_DICT = { NAMES_DICT = {
"raw": "D05A5FE3-15FB-49A1-A15D-AB3DA6F8B068.jpeg", "raw": "DSC03584.jpeg",
"heic": "7783E8E6-9CAC-40F3-BE22-81FB7051C266.jpeg", "heic": "IMG_3092.jpeg"
} }
UUID_LIVE_HEIC = "612CE30B-3D8F-417A-9B14-EC42CBA10ACC" UUID_LIVE_HEIC = "612CE30B-3D8F-417A-9B14-EC42CBA10ACC"
NAMES_LIVE_HEIC = [ NAMES_LIVE_HEIC = [
"612CE30B-3D8F-417A-9B14-EC42CBA10ACC.jpeg", "IMG_3259.jpeg",
"612CE30B-3D8F-417A-9B14-EC42CBA10ACC.mov", "IMG_3259.mov"
] ]

View File

@@ -29,13 +29,13 @@ def test_export_1():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)[0] got_dest = photos[0].export(dest)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
assert os.path.isfile(got_dest) assert os.path.isfile(got_dest)
assert pathlib.Path(got_dest).name == FILENAME_DICT["current"] assert pathlib.Path(got_dest).name == FILENAME_DICT["original"]
def test_export_2(): def test_export_2():
@@ -101,7 +101,7 @@ def test_export_edited_default():
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
got_dest = photos[0].export(dest, edited=True)[0] got_dest = photos[0].export(dest, edited=True)[0]
assert pathlib.Path(got_dest).name == FILENAME_DICT["current_edited"] assert pathlib.Path(got_dest).name == FILENAME_DICT["original_edited"]
def test_export_edited_wrong_suffix(): def test_export_edited_wrong_suffix():

View File

@@ -21,6 +21,8 @@ EXPORT_RESULT_ATTRIBUTES = [
"error", "error",
"exiftool_warning", "exiftool_warning",
"exiftool_error", "exiftool_error",
"deleted_files",
"deleted_directories",
] ]
@@ -43,6 +45,8 @@ def test_exportresults_init():
assert results.error == [] assert results.error == []
assert results.exiftool_warning == [] assert results.exiftool_warning == []
assert results.exiftool_error == [] assert results.exiftool_error == []
assert results.deleted_files == []
assert results.deleted_directories == []
def test_exportresults_iadd(): def test_exportresults_iadd():
@@ -64,6 +68,12 @@ def test_exportresults_iadd():
results1.exiftool_error = [("exiftool_error1", "foo")] results1.exiftool_error = [("exiftool_error1", "foo")]
results2.exiftool_error = [("exiftool_error2", "bar")] results2.exiftool_error = [("exiftool_error2", "bar")]
results1.deleted_files = [("foo1")]
results2.deleted_files = [("foo2")]
results1.deleted_directories = [("bar1")]
results2.deleted_directories = [("bar2")]
results1 += results2 results1 += results2
assert results1.exiftool_warning == [ assert results1.exiftool_warning == [
@@ -75,6 +85,9 @@ def test_exportresults_iadd():
("exiftool_error2", "bar"), ("exiftool_error2", "bar"),
] ]
assert results1.deleted_files == ["foo1", "foo2"]
assert results1.deleted_directories == ["bar1", "bar2"]
def test_all_files(): def test_all_files():
""" test ExportResults.all_files() """ """ test ExportResults.all_files() """
@@ -84,10 +97,12 @@ def test_all_files():
results.exiftool_warning = [("exiftool_warning1", "foo")] results.exiftool_warning = [("exiftool_warning1", "foo")]
results.exiftool_error = [("exiftool_error1", "foo")] results.exiftool_error = [("exiftool_error1", "foo")]
results.error = [("error1", "foo")] results.error = [("error1", "foo")]
results.deleted_files = ["deleted_files1"]
results.deleted_directories = ["deleted_directories1"]
assert sorted(results.all_files()) == sorted( assert sorted(
[f"{x}1" for x in EXPORT_RESULT_ATTRIBUTES] results.all_files() + results.deleted_files + results.deleted_directories
) ) == sorted([f"{x}1" for x in EXPORT_RESULT_ATTRIBUTES])
def test_str(): def test_str():
@@ -95,6 +110,6 @@ def test_str():
results = ExportResults() results = ExportResults()
assert ( assert (
str(results) str(results)
== "ExportResults(exported=[],new=[],updated=[],skipped=[],exif_updated=[],touched=[],converted_to_jpeg=[],sidecar_json_written=[],sidecar_json_skipped=[],sidecar_exiftool_written=[],sidecar_exiftool_skipped=[],sidecar_xmp_written=[],sidecar_xmp_skipped=[],missing=[],error=[],exiftool_warning=[],exiftool_error=[])" == "ExportResults(exported=[],new=[],updated=[],skipped=[],exif_updated=[],touched=[],converted_to_jpeg=[],sidecar_json_written=[],sidecar_json_skipped=[],sidecar_exiftool_written=[],sidecar_exiftool_skipped=[],sidecar_xmp_written=[],sidecar_xmp_skipped=[],missing=[],error=[],exiftool_warning=[],exiftool_error=[],deleted_files=[],deleted_directories=[])"
) )

View File

@@ -44,7 +44,7 @@ def test_export_live_1():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["live"]]) photos = photosdb.photos(uuid=[UUID_DICT["live"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest.name, filename) expected_dest = os.path.join(dest.name, filename)
got_dest = photos[0].export(dest.name, live_photo=True)[0] got_dest = photos[0].export(dest.name, live_photo=True)[0]
got_movie = f"{pathlib.Path(got_dest).parent / pathlib.Path(got_dest).stem}.mov" got_movie = f"{pathlib.Path(got_dest).parent / pathlib.Path(got_dest).stem}.mov"
@@ -70,7 +70,7 @@ def test_export_live_2():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["live"]]) photos = photosdb.photos(uuid=[UUID_DICT["live"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest.name, filename) expected_dest = os.path.join(dest.name, filename)
got_dest = photos[0].export(dest.name, live_photo=False)[0] got_dest = photos[0].export(dest.name, live_photo=False)[0]
got_movie = f"{pathlib.Path(got_dest).parent / pathlib.Path(got_dest).stem}.mov" got_movie = f"{pathlib.Path(got_dest).parent / pathlib.Path(got_dest).stem}.mov"
@@ -97,7 +97,7 @@ def test_export_live_3():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["live"]]) photos = photosdb.photos(uuid=[UUID_DICT["live"]])
filename = photos[0].filename filename = photos[0].original_filename
expected_dest = os.path.join(dest.name, filename) expected_dest = os.path.join(dest.name, filename)
expected_mov = f"{dest.name}/{pathlib.Path(expected_dest).stem}.mov" expected_mov = f"{dest.name}/{pathlib.Path(expected_dest).stem}.mov"
got_files = photos[0].export(dest.name, live_photo=True) got_files = photos[0].export(dest.name, live_photo=True)