Compare commits
194 Commits
v0.56.2
...
sweep/repl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
170a1795eb | ||
|
|
e53d223f2d | ||
|
|
b36aeedf2b | ||
|
|
009e17b75c | ||
|
|
9227fa19be | ||
|
|
7bdb89f1d5 | ||
|
|
4aa74decd7 | ||
|
|
7cf28fe0d2 | ||
|
|
0e0b4b1b09 | ||
|
|
b833cde599 | ||
|
|
0ff2d50004 | ||
|
|
2875b45d6e | ||
|
|
8fb47d9c40 | ||
|
|
d1d6938581 | ||
|
|
3f74eeff44 | ||
|
|
93e1966607 | ||
|
|
e937285a72 | ||
|
|
284c272183 | ||
|
|
db6caa5fa4 | ||
|
|
ed1486fd4b | ||
|
|
8c49916253 | ||
|
|
201bdacddd | ||
|
|
3999e54f6c | ||
|
|
02b6698c80 | ||
|
|
3bae875a63 | ||
|
|
ea6ecc9767 | ||
|
|
2b1ad4ed7f | ||
|
|
4efc0c9f56 | ||
|
|
25d4015b65 | ||
|
|
1d46c9ce8b | ||
|
|
34fda8bcbc | ||
|
|
45468dd1a9 | ||
|
|
903079a819 | ||
|
|
ff70981fbb | ||
|
|
052f2791ac | ||
|
|
4f0e2a101d | ||
|
|
185c6934b8 | ||
|
|
c0fa8ef262 | ||
|
|
e87a42a3ac | ||
|
|
bf9961e203 | ||
|
|
c63b08694e | ||
|
|
30b0c13b33 | ||
|
|
1977578cfd | ||
|
|
44a46cb652 | ||
|
|
7ed8c7e583 | ||
|
|
0064304574 | ||
|
|
179997aa96 | ||
|
|
889c878138 | ||
|
|
2bac3a9c3e | ||
|
|
3a1a4ad991 | ||
|
|
2190628e82 | ||
|
|
bb8e164f21 | ||
|
|
7ccfe26e37 | ||
|
|
2c80226ec8 | ||
|
|
492e1edb7f | ||
|
|
72c6a165c7 | ||
|
|
e9aa289e8a | ||
|
|
1fd73e5351 | ||
|
|
8de871ccf1 | ||
|
|
0473b45631 | ||
|
|
6b541b83ad | ||
|
|
633f3a92fa | ||
|
|
de0b4fa11f | ||
|
|
269a2dfa9e | ||
|
|
986010ec5f | ||
|
|
e062582d14 | ||
|
|
d30314bedc | ||
|
|
7dfd24cb96 | ||
|
|
fcb015dd4a | ||
|
|
d2338992a2 | ||
|
|
234db3fb54 | ||
|
|
55d4be6892 | ||
|
|
922634ab3e | ||
|
|
f0aa69d8bb | ||
|
|
ee8053d867 | ||
|
|
253901281d | ||
|
|
051da093ea | ||
|
|
fd5b16578c | ||
|
|
ca3da647f2 | ||
|
|
0c85298c03 | ||
|
|
b4b58d3b00 | ||
|
|
ed543aa2d0 | ||
|
|
1b0c91db97 | ||
|
|
dd3914328b | ||
|
|
4b4252a73c | ||
|
|
956cecfa30 | ||
|
|
6f88f19950 | ||
|
|
ce4f3c4c0b | ||
|
|
3993cf220d | ||
|
|
2ae41a5a7a | ||
|
|
519a6b0035 | ||
|
|
a4b4f1c288 | ||
|
|
f668ecf0c4 | ||
|
|
058b56092f | ||
|
|
d2b7783125 | ||
|
|
f4a743468d | ||
|
|
adac985309 | ||
|
|
4939324d2f | ||
|
|
1a3b4c2afe | ||
|
|
1b16a39cef | ||
|
|
0d31a152be | ||
|
|
34fbd87fc6 | ||
|
|
3ddfea6a3d | ||
|
|
8b59615ff7 | ||
|
|
c590a16d70 | ||
|
|
36ce86c4a6 | ||
|
|
93d22c646f | ||
|
|
77000d85c6 | ||
|
|
005f821501 | ||
|
|
622f8952b7 | ||
|
|
b7816be459 | ||
|
|
e7099d250b | ||
|
|
2c4d0f4546 | ||
|
|
84954f4551 | ||
|
|
10ebe9e02b | ||
|
|
6813e9f2b4 | ||
|
|
1d1b69601f | ||
|
|
3ad4c7a4cc | ||
|
|
0dd628682f | ||
|
|
8f7d88d8da | ||
|
|
4fcd381262 | ||
|
|
10d1ea8b2c | ||
|
|
cfb623d19b | ||
|
|
a08680ed02 | ||
|
|
56ca54ad0d | ||
|
|
2e4046c319 | ||
|
|
0b6be87d15 | ||
|
|
b7c98aa548 | ||
|
|
0694662f78 | ||
|
|
7eb35b31ac | ||
|
|
94f484e9ec | ||
|
|
0e1613f134 | ||
|
|
1661cc9f0b | ||
|
|
1981340108 | ||
|
|
c3ca25fe33 | ||
|
|
1e10df26c9 | ||
|
|
8fdecd56f5 | ||
|
|
b2ed70b00c | ||
|
|
3a77a3e5f0 | ||
|
|
e89f8a14b4 | ||
|
|
82295513fe | ||
|
|
e7e3e72f75 | ||
|
|
9006708a30 | ||
|
|
4c2570a81d | ||
|
|
30e81eddb5 | ||
|
|
5aa4a20bb5 | ||
|
|
109917321a | ||
|
|
7fb7a551a8 | ||
|
|
d3267cb0f0 | ||
|
|
1209d98e6e | ||
|
|
c90c241a36 | ||
|
|
206490cacc | ||
|
|
31212a1daa | ||
|
|
a46f8bd244 | ||
|
|
06b02b4a23 | ||
|
|
30c036a287 | ||
|
|
715d874306 | ||
|
|
e39424e906 | ||
|
|
b03670dc70 | ||
|
|
ce297ced0a | ||
|
|
c4788c0fd2 | ||
|
|
98e988cd6a | ||
|
|
b39f52cc35 | ||
|
|
d990670f72 | ||
|
|
97a0a65d8a | ||
|
|
f7ca3977a9 | ||
|
|
fbb05d6795 | ||
|
|
0982d0c548 | ||
|
|
007f0e0960 | ||
|
|
0f1866e39d | ||
|
|
da6c3b8440 | ||
|
|
10c6e91d80 | ||
|
|
0abdf62bef | ||
|
|
9efb99cbd4 | ||
|
|
0c293d0bf5 | ||
|
|
770d85759d | ||
|
|
80ee142c7f | ||
|
|
7f7e58a1bd | ||
|
|
6a6f1da746 | ||
|
|
db5c4a216f | ||
|
|
369fa553e8 | ||
|
|
29968269ff | ||
|
|
381141bc09 | ||
|
|
caa279e394 | ||
|
|
bd01e41714 | ||
|
|
32b23a09cb | ||
|
|
4857598324 | ||
|
|
b937874f66 | ||
|
|
69eb4b070c | ||
|
|
8c46b8e545 | ||
|
|
b6ab618154 | ||
|
|
7ab33f66d7 | ||
|
|
83d14ac191 | ||
|
|
aca2333477 |
@@ -184,7 +184,8 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/42419?v=4",
|
||||
"profile": "https://neilpa.me",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -262,7 +263,8 @@
|
||||
"bug",
|
||||
"ideas",
|
||||
"test",
|
||||
"code"
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -464,8 +466,141 @@
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "djbeadle",
|
||||
"name": "Daniel Beadle",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6235378?v=4",
|
||||
"profile": "https://danielbeadle.net",
|
||||
"contributions": [
|
||||
"ideas"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "eecue",
|
||||
"name": "Dave Bullock",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/532536?v=4",
|
||||
"profile": "http://eecue.com/",
|
||||
"contributions": [
|
||||
"ideas",
|
||||
"userTesting",
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "pweaver",
|
||||
"name": "Pweaver",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/611620?v=4",
|
||||
"profile": "https://github.com/pweaver",
|
||||
"contributions": [
|
||||
"bug",
|
||||
"ideas"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "aa599",
|
||||
"name": "aa599",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/37746269?v=4",
|
||||
"profile": "https://github.com/aa599",
|
||||
"contributions": [
|
||||
"bug",
|
||||
"ideas"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "swduncan",
|
||||
"name": "Steve Duncan",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2053195?v=4",
|
||||
"profile": "https://github.com/swduncan",
|
||||
"contributions": [
|
||||
"ideas"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ianmmoir",
|
||||
"name": "Ian Moir",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/15144745?v=4",
|
||||
"profile": "http://www.projany.com",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "pekingduck",
|
||||
"name": "Peking Duck",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2597142?v=4",
|
||||
"profile": "https://github.com/pekingduck",
|
||||
"contributions": [
|
||||
"ideas",
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "cclauss",
|
||||
"name": "Christian Clauss",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3709715?v=4",
|
||||
"profile": "https://www.patreon.com/cclauss",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dvdkon",
|
||||
"name": "dvdkon",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3526303?v=4",
|
||||
"profile": "https://github.com/dvdkon",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "wernerzj",
|
||||
"name": "wernerzj",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/130370930?v=4",
|
||||
"profile": "https://github.com/wernerzj",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "rajscode",
|
||||
"name": "rajscode",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/99123253?v=4",
|
||||
"profile": "https://github.com/rajscode",
|
||||
"contributions": [
|
||||
"bug",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "MaxLyt",
|
||||
"name": "MaxLyt",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/136200430?v=4",
|
||||
"profile": "https://github.com/MaxLyt",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ces3001",
|
||||
"name": "ces3001",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/23762610?v=4",
|
||||
"profile": "https://github.com/ces3001",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "msolo",
|
||||
"name": "msolo",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5078276?v=4",
|
||||
"profile": "https://github.com/msolo",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
"skipCi": true
|
||||
"skipCi": true,
|
||||
"commitType": "docs"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 0.56.2
|
||||
current_version = 0.61.0
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
|
||||
serialize = {major}.{minor}.{patch}
|
||||
|
||||
|
||||
11
.github/ISSUE_TEMPLATE/sweep-bugfix.yml
vendored
Normal file
11
.github/ISSUE_TEMPLATE/sweep-bugfix.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
name: Bugfix
|
||||
title: 'Sweep: '
|
||||
description: Write something like "We notice ... behavior when ... happens instead of ...""
|
||||
labels: sweep
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Details
|
||||
description: More details about the bug
|
||||
placeholder: The bug might be in ... file
|
||||
11
.github/ISSUE_TEMPLATE/sweep-feature.yml
vendored
Normal file
11
.github/ISSUE_TEMPLATE/sweep-feature.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
name: Feature Request
|
||||
title: 'Sweep: '
|
||||
description: Write something like "Write an api endpoint that does "..." in the "..." file"
|
||||
labels: sweep
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Details
|
||||
description: More details for Sweep
|
||||
placeholder: The new endpoint should use the ... class from ... file because it contains ... logic
|
||||
11
.github/ISSUE_TEMPLATE/sweep-refactor.yml
vendored
Normal file
11
.github/ISSUE_TEMPLATE/sweep-refactor.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
name: Refactor
|
||||
title: 'Sweep: '
|
||||
description: Write something like "Modify the ... api endpoint to use ... version and ... framework"
|
||||
labels: sweep
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Details
|
||||
description: More details for Sweep
|
||||
placeholder: We are migrating this function to ... version because ...
|
||||
15
.github/workflows/tests.yml
vendored
15
.github/workflows/tests.yml
vendored
@@ -3,21 +3,30 @@ name: Tests
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
ruff: # https://beta.ruff.rs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: pip install --user ruff # Lint Python twice: 1. Whole repo, 2. Exclude tests/
|
||||
- run: ruff --format=github --line-length=7228 --target-version=py39
|
||||
--ignore=E402,E712,E721,E722,E741,F401,F403,F405,F541,F601,F811,F822,F841 .
|
||||
- run: ruff --format=github --line-length=366 --target-version=py39
|
||||
--exclude=tests/ --ignore=E402,E722,E741,F401,F403,F405,F541,F822,F841 .
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: "!contains(github.event.head_commit.message, '[skip ci]')"
|
||||
if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }}
|
||||
strategy:
|
||||
max-parallel: 4
|
||||
matrix:
|
||||
os: [macos-latest]
|
||||
os: [macos-latest, ubuntu-latest]
|
||||
python-version: ['3.9', '3.10', '3.11']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip' # caching pip dependencies
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,6 +1,6 @@
|
||||
.metrics
|
||||
.DS_store
|
||||
__pycache__
|
||||
__pycache__/
|
||||
.coverage
|
||||
.condaauto
|
||||
t.out
|
||||
@@ -17,4 +17,4 @@ cli.spec
|
||||
docsrc/_build/
|
||||
venv/
|
||||
.python-version
|
||||
cov.xml
|
||||
cov.xml
|
||||
|
||||
1108
API_README.md
1108
API_README.md
File diff suppressed because it is too large
Load Diff
1479
CHANGELOG.md
1479
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
438
README.md
438
README.md
@@ -7,10 +7,10 @@
|
||||
[](https://pepy.tech/project/osxphotos)
|
||||
[](https://www.reddit.com/r/osxphotos/)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors)
|
||||
[](#contributors)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
OSXPhotos provides the ability to interact with and query Apple's Photos.app library on macOS. You can query the Photos library database — for example, file name, file path, and metadata such as keywords/tags, persons/faces, albums, etc. You can also easily export both the original and edited photos.
|
||||
OSXPhotos provides the ability to interact with and query Apple's Photos.app library on macOS and Linux. You can query the Photos library database — for example, file name, file path, and metadata such as keywords/tags, persons/faces, albums, etc. You can also easily export both the original and edited photos.
|
||||
|
||||
<p align="center"><img src="docs/screencast/demo.gif?raw=true" width="713" height="430"/></p>
|
||||
|
||||
@@ -33,20 +33,26 @@ OSXPhotos provides the ability to interact with and query Apple's Photos.app lib
|
||||
|
||||
## Supported operating systems
|
||||
|
||||
Only works on macOS (aka Mac OS X). Tested on macOS Sierra (10.12.6) through macOS Monterey (12.0.1). Tested on both x86 and Apple silicon (M1).
|
||||
Tested on Ubuntu Linux and macOS. Many features are only available on macOS.
|
||||
|
||||
On Linux, macOS-specific features of the CLI will not be available (these will not be shown in the help output).
|
||||
The export and query CLI commands as well as the Python API will work on Linux which enables you to export photos
|
||||
from a Photos library on a Linux machine.
|
||||
|
||||
Tested on macOS Sierra (10.12.6) through macOS Ventura (13.4). Tested on both x86 and Apple silicon (M1).
|
||||
macOS Sonoma (14.0) is currently supported but is still in alpha testing.
|
||||
|
||||
| macOS Version | macOS name | Photos.app version |
|
||||
| ----------------- |------------|:-------------------|
|
||||
| 13.0 | Ventura | 8.0 ✅ * |
|
||||
| 12.0 - 12.6 | Monterey | 7.0 ✅ * |
|
||||
| 14.0 | Sonoma | 9.0 ✅ (alpha support) |
|
||||
| 13.0 - 13.4 | Ventura | 8.0 ✅ |
|
||||
| 12.0 - 12.6 | Monterey | 7.0 ✅ |
|
||||
| 10.16, 11.0-11.4 | Big Sur | 6.0 ✅ |
|
||||
| 10.15.1 - 10.15.7 | Catalina | 5.0 ✅ |
|
||||
| 10.14.5, 10.14.6 | Mojave | 4.0 ✅ |
|
||||
| 10.13.6 | High Sierra| 3.0 ✅ |
|
||||
| 10.12.6 | Sierra | 2.0 ✅ |
|
||||
|
||||
\* Some features may not be fully supported on Monterey and Ventura. Notably, `--use-photokit` and `--download-missing` may or may not work depending on your configuration; this is a known issue that will be fixed if I can find a solution. Many users successfully use OSXPhotos on Monterey without problem.
|
||||
|
||||
This package will read Photos databases for any supported version on any supported macOS version. E.g. you can read a database created with Photos 5.0 on MacOS 10.15 on a machine running macOS 10.12 and vice versa.
|
||||
|
||||
Requires python >= `3.9`.
|
||||
@@ -70,6 +76,14 @@ Once you've installed osxphotos with pipx, to upgrade to the latest version:
|
||||
|
||||
pipx upgrade osxphotos
|
||||
|
||||
**Note**: When installing other packages with homebrew, homebrew may update the version of Python installed which would then cause any app (including osxphotos) installed with `pipx` to fail. If this happens, the easiest fix is to reinstall osxphotos with:
|
||||
|
||||
pipx reinstall osxphotos
|
||||
|
||||
Alternatively, you can reinstall all apps installed with `pipx` with:
|
||||
|
||||
pipx reinstall-all
|
||||
|
||||
### Installation using pip
|
||||
|
||||
You can also install directly from [pypi](https://pypi.org/project/osxphotos/):
|
||||
@@ -112,56 +126,62 @@ If you have questions, would like to show off projects created with OSXPhotos, o
|
||||
|
||||
This package will install a command line utility called `osxphotos` that allows you to query the Photos database. Alternatively, you can also run the command line utility like this: `python3 -m osxphotos`
|
||||
|
||||
<!--[[[cog
|
||||
from osxphotos.cli import cli_main
|
||||
from click.testing import CliRunner
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli_main, ["--help"])
|
||||
help = result.output.replace("Usage: cli-main", "Usage: osxphotos")
|
||||
cog.out(
|
||||
"```\n{}\n```".format(help)
|
||||
)
|
||||
]]] -->
|
||||
```
|
||||
> osxphotos
|
||||
Usage: osxphotos [OPTIONS] COMMAND [ARGS]...
|
||||
|
||||
osxphotos: query and export your Photos library
|
||||
osxphotos: the multi-tool for your Photos library
|
||||
|
||||
Options:
|
||||
--db PHOTOS_LIBRARY_PATH Specify Photos database path. Path to Photos
|
||||
library/database can be specified using either
|
||||
--db or directly as PHOTOS_LIBRARY positional
|
||||
argument. If neither --db or PHOTOS_LIBRARY
|
||||
provided, will attempt to find the library to use
|
||||
in the following order: 1. last opened library, 2.
|
||||
system library, 3. ~/Pictures/Photos
|
||||
Library.photoslibrary
|
||||
--json Print output in JSON format.
|
||||
-v, --version Show the version and exit.
|
||||
-h, --help Show this message and exit.
|
||||
-v, --version Show the version and exit.
|
||||
-h, --help Show this message and exit.
|
||||
|
||||
Commands:
|
||||
about Print information about osxphotos including license.
|
||||
albums Print out albums found in the Photos library.
|
||||
diff Compare two Photos databases and print out differences
|
||||
docs Open osxphotos documentation in your browser.
|
||||
dump Print list of all photos & associated info from the Photos...
|
||||
exiftool Run exiftool on previously exported files to update metadata.
|
||||
export Export photos from the Photos database.
|
||||
exportdb Utilities for working with the osxphotos export database
|
||||
help Print help; for help on commands: help <command>.
|
||||
import Import photos and videos into Photos.
|
||||
info Print out descriptive info of the Photos library database.
|
||||
inspect Interactively inspect photos selected in Photos.
|
||||
install Install Python packages into the same environment as osxphotos
|
||||
keywords Print out keywords found in the Photos library.
|
||||
labels Print out image classification labels found in the Photos...
|
||||
list Print list of Photos libraries found on the system.
|
||||
orphans Find orphaned photos in a Photos library
|
||||
persons Print out persons (faces) found in the Photos library.
|
||||
places Print out places found in the Photos library.
|
||||
query Query the Photos database using 1 or more search options; if...
|
||||
repl Run interactive osxphotos REPL shell (useful for debugging,...
|
||||
run Run a python file using same environment as osxphotos.
|
||||
snap Create snapshot of Photos database to use with diff command
|
||||
theme Manage osxphotos color themes.
|
||||
timewarp Adjust date/time/timezone of photos in Apple Photos.
|
||||
tutorial Display osxphotos tutorial.
|
||||
uninstall Uninstall Python packages from the osxphotos environment
|
||||
uuid Print out unique IDs (UUID) of photos selected in Photos
|
||||
version Check for new version of osxphotos.
|
||||
about Print information about osxphotos including license.
|
||||
add-locations Add missing location data to photos in Photos.app using...
|
||||
albums Print out albums found in the Photos library.
|
||||
batch-edit Batch edit photo metadata such as title, description,...
|
||||
diff Compare two Photos databases and print out differences
|
||||
docs Open osxphotos documentation in your browser.
|
||||
dump Print list of all photos & associated info from the Photos...
|
||||
exiftool Run exiftool on previously exported files to update metadata.
|
||||
export Export photos from the Photos database.
|
||||
exportdb Utilities for working with the osxphotos export database
|
||||
help Print help; for help on commands: help <command>.
|
||||
import Import photos and videos into Photos.
|
||||
info Print out descriptive info of the Photos library database.
|
||||
inspect Interactively inspect photos selected in Photos.
|
||||
install Install Python packages into the same environment as...
|
||||
keywords Print out keywords found in the Photos library.
|
||||
labels Print out image classification labels found in the Photos...
|
||||
list Print list of Photos libraries found on the system.
|
||||
orphans Find orphaned photos in a Photos library
|
||||
persons Print out persons (faces) found in the Photos library.
|
||||
places Print out places found in the Photos library.
|
||||
query Query the Photos database using 1 or more search options;...
|
||||
repl Run interactive osxphotos REPL shell (useful for...
|
||||
run Run a python file using same environment as osxphotos.
|
||||
show Show photo, album, or folder in Photos from UUID_OR_NAME
|
||||
snap Create snapshot of Photos database to use with diff command
|
||||
sync Sync metadata and albums between Photos libraries.
|
||||
theme Manage osxphotos color themes.
|
||||
timewarp Adjust date/time/timezone of photos in Apple Photos.
|
||||
tutorial Display osxphotos tutorial.
|
||||
uninstall Uninstall Python packages from the osxphotos environment
|
||||
uuid Print out unique IDs (UUID) of photos selected in Photos
|
||||
version Check for new version of osxphotos.
|
||||
|
||||
```
|
||||
<!--[[[end]]] -->
|
||||
|
||||
To get help on a specific command, use `osxphotos help command_name`, for example, `osxphotos help export` to get help on the `export` command.
|
||||
|
||||
@@ -673,15 +693,14 @@ Usage: osxphotos export [OPTIONS] [PHOTOS_LIBRARY]... DEST
|
||||
this behavior.
|
||||
|
||||
Options:
|
||||
--db PHOTOS_LIBRARY_PATH Specify Photos database path. Path to Photos
|
||||
library/database can be specified using either
|
||||
--db or directly as PHOTOS_LIBRARY positional
|
||||
argument. If neither --db or PHOTOS_LIBRARY
|
||||
--library, --db PHOTOS_LIBRARY_PATH
|
||||
Specify path to Photos library. If not
|
||||
provided, will attempt to find the library to
|
||||
use in the following order: 1. last opened
|
||||
library, 2. system library, 3.
|
||||
~/Pictures/Photos Library.photoslibrary
|
||||
-V, --verbose Print verbose output.
|
||||
-V, --verbose Print verbose output; may be specified
|
||||
multiple times for more verbose output.
|
||||
--timestamp Add time stamp to verbose output
|
||||
--no-progress Do not display progress bar during export.
|
||||
--keyword KEYWORD Search for photos with keyword KEYWORD. If
|
||||
@@ -706,8 +725,9 @@ Options:
|
||||
--uuid UUID Search for photos with UUID(s). May be
|
||||
repeated to include multiple UUIDs.
|
||||
--uuid-from-file FILE Search for photos with UUID(s) loaded from
|
||||
FILE. Format is a single UUID per line. Lines
|
||||
preceded with # are ignored.
|
||||
FILE. Format is a single UUID per line. Lines
|
||||
preceded with # are ignored. If FILE is '-',
|
||||
read UUIDs from stdin.
|
||||
--title TITLE Search for TITLE in title of photo.
|
||||
--no-title Search for photos with no title.
|
||||
--description DESC Search for DESC in description of photo.
|
||||
@@ -729,6 +749,7 @@ Options:
|
||||
-i, --ignore-case Case insensitive search for title,
|
||||
description, place, keyword, person, or album.
|
||||
--edited Search for photos that have been edited.
|
||||
--not-edited Search for photos that have not been edited.
|
||||
--external-edit Search for photos edited in external editor.
|
||||
--favorite Search for photos marked favorite.
|
||||
--not-favorite Search for photos not marked favorite.
|
||||
@@ -851,6 +872,20 @@ Options:
|
||||
been synched)
|
||||
--not-incloud Search for photos that are not in iCloud (have
|
||||
not been synched)
|
||||
--syndicated Search for photos that have been shared via
|
||||
syndication ('Shared with You' album via
|
||||
Messages, etc.)
|
||||
--not-syndicated Search for photos that have not been shared
|
||||
via syndication ('Shared with You' album via
|
||||
Messages, etc.)
|
||||
--saved-to-library Search for syndicated photos that have saved
|
||||
to the library
|
||||
--not-saved-to-library Search for syndicated photos that have not
|
||||
saved to the library
|
||||
--shared-moment Search for photos that are part of a shared
|
||||
moment
|
||||
--not-shared-moment Search for photos that are not part of a
|
||||
shared moment
|
||||
--regex REGEX TEMPLATE Search for photos where TEMPLATE matches
|
||||
regular expression REGEX. For example, to find
|
||||
photos in an album that begins with 'Beach': '
|
||||
@@ -898,10 +933,10 @@ Options:
|
||||
evaluated. See https://github.com/RhetTbull/os
|
||||
xphotos/blob/master/examples/query_function.py
|
||||
for example of how to use this option.
|
||||
--deleted Include photos from the 'Recently Deleted'
|
||||
folder.
|
||||
--deleted-only Include only photos from the 'Recently
|
||||
Deleted' folder.
|
||||
--deleted Include photos from the 'Recently Deleted'
|
||||
folder.
|
||||
--update Only export new or updated files. See also
|
||||
--force-update and notes below on export and
|
||||
--update.
|
||||
@@ -1037,6 +1072,14 @@ Options:
|
||||
export all burst images; only the primary
|
||||
photo will be exported--associated burst
|
||||
images will be skipped.
|
||||
--export-aae Also export an adjustments file detailing
|
||||
edits made to the original. The resulting file
|
||||
is named photoname.AAE. Note that to import
|
||||
these files back to Photos succesfully, you
|
||||
also need to export the edited photo and match
|
||||
the filename format Photos.app expects:
|
||||
--filename 'IMG_{edited_version?E,}{id:04d}'
|
||||
--edited-suffix ''
|
||||
--sidecar FORMAT Create sidecar for each photo exported; valid
|
||||
FORMAT values: xmp, json, exiftool; --sidecar
|
||||
xmp: create XMP sidecar used by Digikam, Adobe
|
||||
@@ -1074,6 +1117,61 @@ Options:
|
||||
of different types but the same name in the
|
||||
output directory, e.g. 'IMG_1234.JPG' and
|
||||
'IMG_1234.MOV'.
|
||||
--sidecar-template MAKO_TEMPLATE_FILE SIDECAR_FILENAME_TEMPLATE OPTIONS
|
||||
Create a custom sidecar file for each photo
|
||||
exported with user provided Mako template
|
||||
(MAKO_TEMPLATE_FILE). MAKO_TEMPLATE_FILE must
|
||||
be a valid Mako template (see
|
||||
https://www.makotemplates.org/). The template
|
||||
will passed the following variables: photo
|
||||
(PhotoInfo object for the photo being
|
||||
exported), sidecar_path (pathlib.Path object
|
||||
for the path to the sidecar being written),
|
||||
and photo_path (pathlib.Path object for the
|
||||
path to the exported photo.
|
||||
SIDECAR_FILENAME_TEMPLATE must be a valid
|
||||
template string (see Templating System in
|
||||
help) which will be rendered to generate the
|
||||
filename of the sidecar file. The `{filepath}`
|
||||
template variable may be used in the
|
||||
SIDECAR_FILENAME_TEMPLATE to refer to the
|
||||
filename of the photo being exported. OPTIONS
|
||||
is a comma-separated list of strings providing
|
||||
additional options to the template. Valid
|
||||
options are: write_skipped, strip_whitespace,
|
||||
strip_lines, skip_zero, catch_errors, none.
|
||||
write_skipped will cause the sidecar file to
|
||||
be written even if the photo is skipped during
|
||||
export. If write_skipped is not passed as an
|
||||
option, the sidecar file will not be written
|
||||
if the photo is skipped during export.
|
||||
strip_whitespace and strip_lines indicate
|
||||
whether or not to strip whitespace and blank
|
||||
lines, respectively, from the resulting
|
||||
sidecar file. skip_zero causes the sidecar
|
||||
file to be skipped if the rendered template is
|
||||
zero-length. catch_errors causes errors in the
|
||||
template to be caught and logged but not
|
||||
raised. Without catch_errors, osxphotos will
|
||||
abort the export if an error occurs in the
|
||||
template. For example, to create a sidecar
|
||||
file with extension .xmp using a template file
|
||||
named 'sidecar.mako' and write a sidecar for
|
||||
skipped photos and strip blank lines but not
|
||||
whitespace: `--sidecar-template sidecar.mako
|
||||
'{filepath}.xmp' write_skipped,strip_lines`.
|
||||
To do the same but to drop the photo extension
|
||||
from the sidecar filename: `--sidecar-template
|
||||
sidecar.mako
|
||||
'{filepath.parent}/{filepath.stem}.xmp'
|
||||
write_skipped,strip_lines`. If you are not
|
||||
passing any options, you must pass 'none' as
|
||||
the last argument to --sidecar-template:
|
||||
`--sidecar-template sidecar.mako
|
||||
'{filepath}.xmp' none`. For an example Mako
|
||||
file see https://raw.githubusercontent.com/Rhe
|
||||
tTbull/osxphotos/main/examples/custom_sidecar.
|
||||
mako
|
||||
--exiftool Use exiftool to write metadata directly to
|
||||
exported photos. To use this option, exiftool
|
||||
must be installed and in the path. exiftool
|
||||
@@ -1254,30 +1352,59 @@ Options:
|
||||
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.
|
||||
--keep KEEP_PATH When used with --cleanup, prevents file or
|
||||
directory KEEP_PATH from being deleted when
|
||||
cleanup is run. Use this if there are files in
|
||||
the export directory that you don't want to be
|
||||
deleted when --cleanup is run. KEEP_PATH may
|
||||
be a file path, e.g.
|
||||
'/Volumes/Photos/keep.jpg', or a file path and
|
||||
wild card, e.g. '/Volumes/Photos/*.txt', or a
|
||||
directory, e.g. '/Volumes/Photos/KeepMe'.
|
||||
KEEP_PATH may be an absolute path or a
|
||||
relative path. If it is relative, it must be
|
||||
relative to the export destination. For
|
||||
certain. To prevent files not generated by
|
||||
osxphotos from being deleted, you may specify
|
||||
one or more rulesin a file named
|
||||
`.osxphotos_keep` in the export directory.
|
||||
This file uses the same format as a .gitignore
|
||||
file and should contain one rule per line;
|
||||
lines starting with a `#` will be ignored.
|
||||
Reference https://git-
|
||||
scm.com/docs/gitignore#_pattern_format for
|
||||
details. In addition to the standard
|
||||
.gitignore rules, the rules may also be the
|
||||
absolute path to a file or directory. For
|
||||
example if export destination is
|
||||
`/Volumes/Photos` and you want to keep all
|
||||
`.txt` files, you can specify `--keep
|
||||
"/Volumes/Photos/*.txt"` or `--keep "*.txt"`.
|
||||
If wild card is used, KEEP_PATH must be
|
||||
enclosed in quotes to prevent the shell from
|
||||
expanding the wildcard, e.g. `--keep
|
||||
"/Volumes/Photos/*.txt"`. If KEEP_PATH is a
|
||||
directory, all files and directories contained
|
||||
in KEEP_PATH will be kept. --keep may be
|
||||
repeated to keep additional files/directories.
|
||||
`.txt` files, in the top level of the export
|
||||
directory, you can specify `/*.txt"` in the
|
||||
.osxphotos_keep file. If you want to keep all
|
||||
`.txt` files in the export directory and all
|
||||
subdirectories, you can specify `**/*.txt`. If
|
||||
present, the .osxphotos_keep file will be read
|
||||
after the export is completed and any rules
|
||||
found in the file will be added to the list of
|
||||
rules to keep. See also --keep.
|
||||
--keep KEEP_RULE When used with --cleanup, prevents file or
|
||||
directory matching KEEP_RULE from being
|
||||
deleted when cleanup is run. Use this if there
|
||||
are files in the export directory that you
|
||||
don't want to be deleted when --cleanup is
|
||||
run. KEEP_RULE follows the same format rules a
|
||||
.gitignore file. Reference https://git-
|
||||
scm.com/docs/gitignore#_pattern_format for
|
||||
details. In addition to the standard
|
||||
.gitignore rules, KEEP_RULE may also be the
|
||||
absolute path to a file or directory. For
|
||||
example if export destination is
|
||||
`/Volumes/Photos` and you want to keep all
|
||||
`.txt` files, in the top level of the export
|
||||
directory, you can specify `--keep "/*.txt"`.
|
||||
If you want to keep all `.txt` files in the
|
||||
export directory and all subdirectories, you
|
||||
can specify `--keep "**/*.txt"`. If wild card
|
||||
is used, KEEP_RULE must be enclosed in quotes
|
||||
to prevent the shell from expanding the
|
||||
wildcard. --keep may be repeated to keep
|
||||
additional files/directories. Rules may also
|
||||
be included in a file named `.osxphotos_keep`
|
||||
in the export directory. If present, this file
|
||||
will be read after the export is completed and
|
||||
any rules found in the file will be added to
|
||||
the list of rules to keep. This file uses the
|
||||
same format as a .gitignore file and should
|
||||
contain one rule per line; lines starting with
|
||||
a `#` will be ignored.
|
||||
--add-exported-to-album ALBUM Add all exported photos to album ALBUM in
|
||||
Photos. Album ALBUM will be created if it
|
||||
doesn't exist. All exported photos will be
|
||||
@@ -1321,8 +1448,18 @@ Options:
|
||||
full path of all exported files to the file
|
||||
'exported.txt'. You can run more than one
|
||||
command by repeating the '--post-command'
|
||||
option with different arguments. See Post
|
||||
Command below.
|
||||
option with different arguments. See also
|
||||
--post-command-error and --post-function.See
|
||||
Post Command below.
|
||||
--post-command-error ACTION Specify either `continue` or `break` for
|
||||
ACTION to control behavior when a post-command
|
||||
fails. If `continue`, osxphotos will log the
|
||||
error and continue processing. If `break`,
|
||||
osxphotos will stop processing any additional
|
||||
--post-command commands for the current photo
|
||||
but will continue with the export. Without
|
||||
--post-command-error, osxphotos will abort the
|
||||
export if a post-command encounters an error.
|
||||
--post-function filename.py::function
|
||||
Run function on exported files. Use this in
|
||||
format: --post-function filename.py::function
|
||||
@@ -1386,10 +1523,10 @@ Options:
|
||||
will be printed after the photo is exported or
|
||||
skipped. May be repeated to print multiple
|
||||
template strings.
|
||||
--theme THEME Specify the color theme to use for --verbose
|
||||
output. Valid themes are 'dark', 'light',
|
||||
'mono', and 'plain'. Defaults to 'dark' or
|
||||
'light' depending on system dark mode setting.
|
||||
--theme THEME Specify the color theme to use for output.
|
||||
Valid themes are 'dark', 'light', 'mono', and
|
||||
'plain'. Defaults to 'dark' or 'light'
|
||||
depending on system dark mode setting.
|
||||
-h, --help Show this message and exit.
|
||||
|
||||
Export
|
||||
@@ -1426,22 +1563,23 @@ option to re-export the entire library thus rebuilding the
|
||||
|
||||
Extended Attributes
|
||||
|
||||
Some options (currently '--finder-tag-template', '--finder-tag-keywords',
|
||||
'-xattr-template') write additional metadata accessible by Spotlight to
|
||||
facilitate searching. For example, --finder-tag-keyword writes all keywords
|
||||
(including any specified by '--keyword-template' or other options) to Finder
|
||||
tags that are searchable in Spotlight using the syntax: 'tag:tagname'. For
|
||||
example, if you have images with keyword "Travel" then using '--finder-tag-
|
||||
keywords' you could quickly find those images in the Finder by typing
|
||||
'tag:Travel' in the Spotlight search bar. Finder tags are written to the
|
||||
'com.apple.metadata:_kMDItemUserTags' extended attribute. Unlike EXIF
|
||||
metadata, extended attributes do not modify the actual file; the metadata is
|
||||
written to extended attributes associated with the file and the Spotlight
|
||||
metadata database. Most cloud storage services do not synch extended
|
||||
attributes. Dropbox does sync them and any changes to a file's extended
|
||||
attributes will cause Dropbox to re-sync the files.
|
||||
Some options (currently '--finder-tag-template', '--finder-tag-keywords',
|
||||
'-xattr-template') write additional metadata accessible by Spotlight
|
||||
to facilitate searching. For example, --finder-tag-keyword writes all
|
||||
keywords (including any specified by '--keyword-template' or other
|
||||
options) to Finder tags that are searchable in Spotlight using the syntax:
|
||||
'tag:tagname'. For example, if you have images with keyword "Travel"
|
||||
then using '--finder-tag-keywords' you could quickly find those images
|
||||
in the Finder by typing 'tag:Travel' in the Spotlight search bar.
|
||||
Finder tags are written to the 'com.apple.metadata:_kMDItemUserTags'
|
||||
extended attribute. Unlike EXIF metadata, extended attributes do not
|
||||
modify the actual file; the metadata is written to extended attributes
|
||||
associated with the file and the Spotlight metadata database. Most
|
||||
cloud storage services do not synch extended attributes. Dropbox does
|
||||
sync them and any changes to a file's extended attributes will cause
|
||||
Dropbox to re-sync the files.
|
||||
|
||||
The following attributes may be used with '--xattr-template':
|
||||
The following attributes may be used with '--xattr-template':
|
||||
|
||||
|
||||
Attribute Description
|
||||
@@ -1585,6 +1723,10 @@ Valid filters are:
|
||||
['a', 'b', 'c', 'd'].
|
||||
• prepend(x): Prepend x to list of values, e.g. prepend(d): ['a', 'b', 'c']
|
||||
=> ['d', 'a', 'b', 'c'].
|
||||
• appends(x): Append s[tring] Append x to each value of list of values, e.g.
|
||||
appends(d): ['a', 'b', 'c'] => ['ad', 'bd', 'cd'].
|
||||
• prepends(x): Prepend s[tring] x to each value of list of values, e.g.
|
||||
prepends(d): ['a', 'b', 'c'] => ['da', 'db', 'dc'].
|
||||
• remove(x): Remove x from list of values, e.g. remove(b): ['a', 'b', 'c'] =>
|
||||
['a', 'c'].
|
||||
• slice(start:stop:step): Slice list using same semantics as Python's list
|
||||
@@ -1739,19 +1881,20 @@ e.g. "{created.year}/{openbrace}{title}{closebrace}" would result in
|
||||
Variables
|
||||
|
||||
You can define variables for later use in the template string using the format
|
||||
{var:NAME,VALUE}. Variables may then be referenced using the format %NAME.
|
||||
For example: {var:foo,bar} defines the variable %foo to have value bar. This
|
||||
can be useful if you want to re-use a complex template value in multiple
|
||||
places within your template string or for allowing the use of characters that
|
||||
would otherwise be prohibited in a template string. For example, the "pipe"
|
||||
(|) character is not allowed in a find/replace pair but you can get around
|
||||
this limitation like so: {var:pipe,{pipe}}{title[-,%pipe]} which replaces the
|
||||
- character with | (the value of %pipe).
|
||||
{var:NAME,VALUE} where VALUE is a template statement. Variables may then be
|
||||
referenced using the format %NAME. For example: {var:foo,bar} defines the
|
||||
variable %foo to have value bar. This can be useful if you want to re-use a
|
||||
complex template value in multiple places within your template string or for
|
||||
allowing the use of characters that would otherwise be prohibited in a
|
||||
template string. For example, the "pipe" (|) character is not allowed in a
|
||||
find/replace pair but you can get around this limitation like so:
|
||||
{var:pipe,{pipe}}{title[-,%pipe]} which replaces the - character with | (the
|
||||
value of %pipe).
|
||||
|
||||
Variables can also be referenced as fields in the template string, for
|
||||
example: {var:year,created.year}{original_name}-{%year}. In some cases, use of
|
||||
variables can make your template string more readable. Variables can be used
|
||||
as template fields, as values for filters, as values for conditional
|
||||
example: {var:year,{created.year}}{original_name}-{%year}. In some cases, use
|
||||
of variables can make your template string more readable. Variables can be
|
||||
used as template fields, as values for filters, as values for conditional
|
||||
operations, or as default values. When used as a conditional value or default
|
||||
value, variables should be treated like any other field and enclosed in braces
|
||||
as conditional and default values are evaluated as template strings. For
|
||||
@@ -1981,6 +2124,41 @@ Substitution Description
|
||||
as a 5-digit integer and pad with zeros, use
|
||||
'{id:05d}' which results in 00001, 00002,
|
||||
00003...etc.
|
||||
{counter} A sequential counter, starting at 0, that
|
||||
increments each time it is evaluated.To
|
||||
start counting at a value other than 0,
|
||||
append append '(starting_value)' to the
|
||||
field name.For example, to start counting at
|
||||
1 instead of 0: '{counter(1)}'.May be
|
||||
formatted using a python string format
|
||||
code.For example, to format as a 5-digit
|
||||
integer and pad with zeros, use
|
||||
'{counter:05d(1)}'which results in 00001,
|
||||
00002, 00003...etc.You may also specify a
|
||||
stop value which causes the counter to reset
|
||||
to the starting valuewhen the stop value is
|
||||
reached and a step size which causes the
|
||||
counter to increment bythe specified value
|
||||
instead of 1. Use the format
|
||||
'{counter(start,stop,step)}' where
|
||||
start,stop, and step are integers. For
|
||||
example, to count from 1 to 10 by 2, use
|
||||
'{counter(1,11,2)}'.Note that the counter
|
||||
stops counting when the stop value is
|
||||
reached and does not return thestop value.
|
||||
Start, stop, and step are optional and may
|
||||
be omitted. For example, to countfrom 0 by
|
||||
2s, use '{counter(,,2)}'.You may create an
|
||||
arbitrary number of counters by appending a
|
||||
unique name to the field namepreceded by a
|
||||
period: '{counter.a}', '{counter.b}', etc.
|
||||
Each counter will have its own stateand will
|
||||
start at 0 and increment by 1 unless
|
||||
otherwise specified. Note: {counter} is not
|
||||
suitable for use with 'export' and '--
|
||||
update' as the counter associated with a
|
||||
photo may change between export sessions.
|
||||
See also {id}.
|
||||
{album_seq} An integer, starting at 0, indicating the
|
||||
photo's index (sequence) in the containing
|
||||
album. Only valid when used in a '--
|
||||
@@ -2041,7 +2219,7 @@ Substitution Description
|
||||
{cr} A carriage return: '\r'
|
||||
{crlf} A carriage return + line feed: '\r\n'
|
||||
{tab} :A tab: '\t'
|
||||
{osxphotos_version} The osxphotos version, e.g. '0.56.2'
|
||||
{osxphotos_version} The osxphotos version, e.g. '0.61.0'
|
||||
{osxphotos_cmd_line} The full command line used to run osxphotos
|
||||
|
||||
The following substitutions may result in multiple values. Thus if specified
|
||||
@@ -2264,6 +2442,7 @@ OSXPhotos adheres to the [XDG](https://specifications.freedesktop.org/basedir-sp
|
||||
* `$XDG_DATA_HOME` or `$HOME/.local/share`: `osxphotos` directory containing local data files, for example, the help files displayed with `osxphotos docs`.
|
||||
* Current working dir: `osxphotos_crash.log` file containing the stack trace of the last crash if OSXPhotos encounters a fatal error during execution.
|
||||
* export directory (when running `osxphotos export` command): `.osxphotos_export.db` [SQLite](https://www.sqlite.org/index.html) database containing information needed to update an export and track metadata changes in exported photos. *Note*: This file may contain sensitive information such as locations and the names of persons in photos so if you are using `osxphotos export` to share with others, you may want to delete this file. You can also specify an alternate location for the export database using the `--exportdb` flag during export. See also `osxphotos help exportdb` for more information about built in utilities for working with the export database.
|
||||
* While osxphotos does not create the file, if present in the root of the export directory, osxphotos will read the file `.osxphotos_keep` to load a list of file/directory patterns which should be excluded from `--cleanup` during export. This file uses the same rule format as [.gitignore](https://git-scm.com/docs/gitignore). See `osxphotos help export cleanup` for more information.
|
||||
|
||||
## Python API
|
||||
|
||||
@@ -2328,6 +2507,8 @@ Valid filters are:
|
||||
- `join(x)`: Join list of values with delimiter x, e.g. join(,): ['a', 'b', 'c'] => 'a,b,c'; the DELIM option functions similar to join(x) but with DELIM, the join happens before being passed to any filters.May optionally be used without an argument, that is 'join()' which joins values together with no delimiter. e.g. join(): ['a', 'b', 'c'] => 'abc'.
|
||||
- `append(x)`: Append x to list of values, e.g. append(d): ['a', 'b', 'c'] => ['a', 'b', 'c', 'd'].
|
||||
- `prepend(x)`: Prepend x to list of values, e.g. prepend(d): ['a', 'b', 'c'] => ['d', 'a', 'b', 'c'].
|
||||
- `appends(x)`: Append s[tring] Append x to each value of list of values, e.g. appends(d): ['a', 'b', 'c'] => ['ad', 'bd', 'cd'].
|
||||
- `prepends(x)`: Prepend s[tring] x to each value of list of values, e.g. prepends(d): ['a', 'b', 'c'] => ['da', 'db', 'dc'].
|
||||
- `remove(x)`: Remove x from list of values, e.g. remove(b): ['a', 'b', 'c'] => ['a', 'c'].
|
||||
- `slice(start:stop:step)`: Slice list using same semantics as Python's list slicing, e.g. slice(1:3): ['a', 'b', 'c', 'd'] => ['b', 'c']; slice(1:4:2): ['a', 'b', 'c', 'd'] => ['b', 'd']; slice(1:): ['a', 'b', 'c', 'd'] => ['b', 'c', 'd']; slice(:-1): ['a', 'b', 'c', 'd'] => ['a', 'b', 'c']; slice(::-1): ['a', 'b', 'c', 'd'] => ['d', 'c', 'b', 'a']. See also sslice().
|
||||
- `sslice(start:stop:step)`: [s(tring) slice] Slice values in a list using same semantics as Python's string slicing, e.g. sslice(1:3):'abcd => 'bc'; sslice(1:4:2): 'abcd' => 'bd', etc. See also slice().
|
||||
@@ -2421,9 +2602,9 @@ e.g. `"{created.year}/{openbrace}{title}{closebrace}"` would result in `"2020/{P
|
||||
|
||||
**Variables**
|
||||
|
||||
You can define variables for later use in the template string using the format `{var:NAME,VALUE}`. Variables may then be referenced using the format `%NAME`. For example: `{var:foo,bar}` defines the variable `%foo` to have value `bar`. This can be useful if you want to re-use a complex template value in multiple places within your template string or for allowing the use of characters that would otherwise be prohibited in a template string. For example, the "pipe" (`|`) character is not allowed in a find/replace pair but you can get around this limitation like so: `{var:pipe,{pipe}}{title[-,%pipe]}` which replaces the `-` character with `|` (the value of `%pipe`).
|
||||
You can define variables for later use in the template string using the format `{var:NAME,VALUE}` where `VALUE` is a template statement. Variables may then be referenced using the format `%NAME`. For example: `{var:foo,bar}` defines the variable `%foo` to have value `bar`. This can be useful if you want to re-use a complex template value in multiple places within your template string or for allowing the use of characters that would otherwise be prohibited in a template string. For example, the "pipe" (`|`) character is not allowed in a find/replace pair but you can get around this limitation like so: `{var:pipe,{pipe}}{title[-,%pipe]}` which replaces the `-` character with `|` (the value of `%pipe`).
|
||||
|
||||
Variables can also be referenced as fields in the template string, for example: `{var:year,created.year}{original_name}-{%year}`. In some cases, use of variables can make your template string more readable. Variables can be used as template fields, as values for filters, as values for conditional operations, or as default values. When used as a conditional value or default value, variables should be treated like any other field and enclosed in braces as conditional and default values are evaluated as template strings. For example: `{var:name,Katie}{person contains {%name}?{%name},Not-{%name}}`.
|
||||
Variables can also be referenced as fields in the template string, for example: `{var:year,{created.year}}{original_name}-{%year}`. In some cases, use of variables can make your template string more readable. Variables can be used as template fields, as values for filters, as values for conditional operations, or as default values. When used as a conditional value or default value, variables should be treated like any other field and enclosed in braces as conditional and default values are evaluated as template strings. For example: `{var:name,Katie}{person contains {%name}?{%name},Not-{%name}}`.
|
||||
|
||||
If you need to use a `%` (percent sign character), you can escape the percent sign by using `%%`. You can also use the `{percent}` template field where a template field is required. For example:
|
||||
|
||||
@@ -2508,6 +2689,7 @@ The following template field substitutions are availabe for use the templating s
|
||||
|{uuid}|Photo's internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'|
|
||||
|{shortuuid}|A shorter representation of photo's internal universally unique identifier (UUID) for the photo, a 22-character string unique to the photo, e.g. 'JYsxugP9UjetmCbBCHXcmu'|
|
||||
|{id}|A unique number for the photo based on its primary key in the Photos database. A sequential integer, e.g. 1, 2, 3...etc. Each asset associated with a photo (e.g. an image and Live Photo preview) will share the same id. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{id:05d}' which results in 00001, 00002, 00003...etc. |
|
||||
|{counter}|A sequential counter, starting at 0, that increments each time it is evaluated.To start counting at a value other than 0, append append '(starting_value)' to the field name.For example, to start counting at 1 instead of 0: '{counter(1)}'.May be formatted using a python string format code.For example, to format as a 5-digit integer and pad with zeros, use '{counter:05d(1)}'which results in 00001, 00002, 00003...etc.You may also specify a stop value which causes the counter to reset to the starting valuewhen the stop value is reached and a step size which causes the counter to increment bythe specified value instead of 1. Use the format '{counter(start,stop,step)}' where start,stop, and step are integers. For example, to count from 1 to 10 by 2, use '{counter(1,11,2)}'.Note that the counter stops counting when the stop value is reached and does not return thestop value. Start, stop, and step are optional and may be omitted. For example, to countfrom 0 by 2s, use '{counter(,,2)}'.You may create an arbitrary number of counters by appending a unique name to the field namepreceded by a period: '{counter.a}', '{counter.b}', etc. Each counter will have its own stateand will start at 0 and increment by 1 unless otherwise specified. Note: {counter} is not suitable for use with 'export' and '--update' as the counter associated with a photo may change between export sessions. See also {id}.|
|
||||
|{album_seq}|An integer, starting at 0, indicating the photo's index (sequence) in the containing album. Only valid when used in a '--filename' template and only when '{album}' or '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{album_seq}_{original_name}"'. To start counting at a value other than 0, append append '(starting_value)' to the field name. For example, to start counting at 1 instead of 0: '{album_seq(1)}'. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{album_seq:05d}' which results in 00000, 00001, 00002...etc. To format while also using a starting value: '{album_seq:05d(1)}' which results in 0001, 00002...etc.This may result in incorrect sequences if you have duplicate albums with the same name; see also '{folder_album_seq}'.|
|
||||
|{folder_album_seq}|An integer, starting at 0, indicating the photo's index (sequence) in the containing album and folder path. Only valid when used in a '--filename' template and only when '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{folder_album_seq}_{original_name}"'. To start counting at a value other than 0, append '(starting_value)' to the field name. For example, to start counting at 1 instead of 0: '{folder_album_seq(1)}' May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{folder_album_seq:05d}' which results in 00000, 00001, 00002...etc. To format while also using a starting value: '{folder_album_seq:05d(1)}' which results in 0001, 00002...etc.This may result in incorrect sequences if you have duplicate albums with the same name in the same folder; see also '{album_seq}'. |
|
||||
|{comma}|A comma: ','|
|
||||
@@ -2525,7 +2707,7 @@ The following template field substitutions are availabe for use the templating s
|
||||
|{cr}|A carriage return: '\r'|
|
||||
|{crlf}|A carriage return + line feed: '\r\n'|
|
||||
|{tab}|:A tab: '\t'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.56.2'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.61.0'|
|
||||
|{osxphotos_cmd_line}|The full command line used to run osxphotos|
|
||||
|{album}|Album(s) photo is contained in|
|
||||
|{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder|
|
||||
@@ -2565,7 +2747,7 @@ I'll gladly consider pull requests for bug fixes or feature implementations.
|
||||
|
||||
If you have an interesting example that shows usage of this package, submit an issue or pull request and i'll include it or link to it.
|
||||
|
||||
Testing against "real world" Photos libraries would be especially helpful. If you discover issues in testing against your Photos libraries, please open an issue. I've done extensive testing against my own Photos library but that's a since data point and I'm certain there are issues lurking in various edge cases I haven't discovered yet.
|
||||
Testing against "real world" Photos libraries would be especially helpful. If you discover issues in testing against your Photos libraries, please open an issue. I've done extensive testing against my own Photos library but that's a single data point and I'm certain there are issues lurking in various edge cases I haven't discovered yet.
|
||||
|
||||
### Contributors ✨
|
||||
|
||||
@@ -2599,7 +2781,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/narensankar0529"><img src="https://avatars3.githubusercontent.com/u/74054766?v=4?s=75" width="75px;" alt="narensankar0529"/><br /><sub><b>narensankar0529</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Anarensankar0529" title="Bug reports">🐛</a> <a href="#userTesting-narensankar0529" title="User Testing">📓</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/martinhrpi"><img src="https://avatars2.githubusercontent.com/u/19407684?v=4?s=75" width="75px;" alt="Martin"/><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" valign="top" width="14.28%"><a href="https://github.com/davidjroos"><img src="https://avatars.githubusercontent.com/u/15630844?v=4?s=75" width="75px;" alt="davidjroos "/><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" valign="top" width="14.28%"><a href="https://neilpa.me"><img src="https://avatars.githubusercontent.com/u/42419?v=4?s=75" width="75px;" alt="Neil Pankey"/><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" valign="top" width="14.28%"><a href="https://neilpa.me"><img src="https://avatars.githubusercontent.com/u/42419?v=4?s=75" width="75px;" alt="Neil Pankey"/><br /><sub><b>Neil Pankey</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/commits?author=neilpa" title="Code">💻</a> <a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Aneilpa" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://aaronweb.net/"><img src="https://avatars.githubusercontent.com/u/604665?v=4?s=75" width="75px;" alt="Aaron van Geffen"/><br /><sub><b>Aaron van Geffen</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/commits?author=AaronVanGeffen" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ubrandes"><img src="https://avatars.githubusercontent.com/u/59647284?v=4?s=75" width="75px;" alt="ubrandes "/><br /><sub><b>ubrandes </b></sub></a><br /><a href="#ideas-ubrandes" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
</tr>
|
||||
@@ -2609,7 +2791,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mkirkland4874"><img src="https://avatars.githubusercontent.com/u/36466711?v=4?s=75" width="75px;" alt="mkirkland4874"/><br /><sub><b>mkirkland4874</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Amkirkland4874" title="Bug reports">🐛</a> <a href="#example-mkirkland4874" title="Examples">💡</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jcommisso07"><img src="https://avatars.githubusercontent.com/u/3111054?v=4?s=75" width="75px;" alt="Joseph Commisso"/><br /><sub><b>Joseph Commisso</b></sub></a><br /><a href="#data-jcommisso07" title="Data">🔣</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dssinger"><img src="https://avatars.githubusercontent.com/u/1817903?v=4?s=75" width="75px;" alt="David Singer"/><br /><sub><b>David Singer</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Adssinger" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/oPromessa"><img src="https://avatars.githubusercontent.com/u/21261491?v=4?s=75" width="75px;" alt="oPromessa"/><br /><sub><b>oPromessa</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3AoPromessa" title="Bug reports">🐛</a> <a href="#ideas-oPromessa" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/RhetTbull/osxphotos/commits?author=oPromessa" title="Tests">⚠️</a> <a href="https://github.com/RhetTbull/osxphotos/commits?author=oPromessa" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/oPromessa"><img src="https://avatars.githubusercontent.com/u/21261491?v=4?s=75" width="75px;" alt="oPromessa"/><br /><sub><b>oPromessa</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3AoPromessa" title="Bug reports">🐛</a> <a href="#ideas-oPromessa" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/RhetTbull/osxphotos/commits?author=oPromessa" title="Tests">⚠️</a> <a href="https://github.com/RhetTbull/osxphotos/commits?author=oPromessa" title="Code">💻</a> <a href="https://github.com/RhetTbull/osxphotos/commits?author=oPromessa" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://spencerchang.me"><img src="https://avatars.githubusercontent.com/u/14796580?v=4?s=75" width="75px;" alt="Spencer Chang"/><br /><sub><b>Spencer Chang</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Aspencerc99" title="Bug reports">🐛</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -2637,6 +2819,24 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://qkeddy.github.io/quin-eddy-development-portfolio/"><img src="https://avatars.githubusercontent.com/u/9737814?v=4?s=75" width="75px;" alt="Quin Eddy"/><br /><sub><b>Quin Eddy</b></sub></a><br /><a href="#ideas-qkeddy" title="Ideas, Planning, & Feedback">🤔</a> <a href="#data-qkeddy" title="Data">🔣</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/johnsturgeon"><img src="https://avatars.githubusercontent.com/u/9746310?v=4?s=75" width="75px;" alt="John Sturgeon"/><br /><sub><b>John Sturgeon</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Ajohnsturgeon" title="Bug reports">🐛</a> <a href="https://github.com/RhetTbull/osxphotos/commits?author=johnsturgeon" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mave2k"><img src="https://avatars.githubusercontent.com/u/8629837?v=4?s=75" width="75px;" alt="mave2k"/><br /><sub><b>mave2k</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/commits?author=mave2k" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://danielbeadle.net"><img src="https://avatars.githubusercontent.com/u/6235378?v=4?s=75" width="75px;" alt="Daniel Beadle"/><br /><sub><b>Daniel Beadle</b></sub></a><br /><a href="#ideas-djbeadle" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://eecue.com/"><img src="https://avatars.githubusercontent.com/u/532536?v=4?s=75" width="75px;" alt="Dave Bullock"/><br /><sub><b>Dave Bullock</b></sub></a><br /><a href="#ideas-eecue" title="Ideas, Planning, & Feedback">🤔</a> <a href="#userTesting-eecue" title="User Testing">📓</a> <a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Aeecue" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pweaver"><img src="https://avatars.githubusercontent.com/u/611620?v=4?s=75" width="75px;" alt="Pweaver"/><br /><sub><b>Pweaver</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Apweaver" title="Bug reports">🐛</a> <a href="#ideas-pweaver" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aa599"><img src="https://avatars.githubusercontent.com/u/37746269?v=4?s=75" width="75px;" alt="aa599"/><br /><sub><b>aa599</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Aaa599" title="Bug reports">🐛</a> <a href="#ideas-aa599" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/swduncan"><img src="https://avatars.githubusercontent.com/u/2053195?v=4?s=75" width="75px;" alt="Steve Duncan"/><br /><sub><b>Steve Duncan</b></sub></a><br /><a href="#ideas-swduncan" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.projany.com"><img src="https://avatars.githubusercontent.com/u/15144745?v=4?s=75" width="75px;" alt="Ian Moir"/><br /><sub><b>Ian Moir</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Aianmmoir" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pekingduck"><img src="https://avatars.githubusercontent.com/u/2597142?v=4?s=75" width="75px;" alt="Peking Duck"/><br /><sub><b>Peking Duck</b></sub></a><br /><a href="#ideas-pekingduck" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Apekingduck" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.patreon.com/cclauss"><img src="https://avatars.githubusercontent.com/u/3709715?v=4?s=75" width="75px;" alt="Christian Clauss"/><br /><sub><b>Christian Clauss</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/commits?author=cclauss" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dvdkon"><img src="https://avatars.githubusercontent.com/u/3526303?v=4?s=75" width="75px;" alt="dvdkon"/><br /><sub><b>dvdkon</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/commits?author=dvdkon" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wernerzj"><img src="https://avatars.githubusercontent.com/u/130370930?v=4?s=75" width="75px;" alt="wernerzj"/><br /><sub><b>wernerzj</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Awernerzj" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rajscode"><img src="https://avatars.githubusercontent.com/u/99123253?v=4?s=75" width="75px;" alt="rajscode"/><br /><sub><b>rajscode</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Arajscode" title="Bug reports">🐛</a> <a href="https://github.com/RhetTbull/osxphotos/commits?author=rajscode" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MaxLyt"><img src="https://avatars.githubusercontent.com/u/136200430?v=4?s=75" width="75px;" alt="MaxLyt"/><br /><sub><b>MaxLyt</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3AMaxLyt" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ces3001"><img src="https://avatars.githubusercontent.com/u/23762610?v=4?s=75" width="75px;" alt="ces3001"/><br /><sub><b>ces3001</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Aces3001" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/msolo"><img src="https://avatars.githubusercontent.com/u/5078276?v=4?s=75" width="75px;" alt="msolo"/><br /><sub><b>msolo</b></sub></a><br /><a href="https://github.com/RhetTbull/osxphotos/issues?q=author%3Amsolo" title="Bug reports">🐛</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -7,7 +7,7 @@ These are notes for developers working on osxphotos. They're mostly to help me r
|
||||
- Clone the repo: `git clone git@github.com:RhetTbull/osxphotos.git`
|
||||
- Create a virtual environment and activate it: `python3 -m venv venv` then `source venv/bin/activate`. I use [pyenv](https://github.com/pyenv/pyenv) with [pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv) to manage my virtual environments
|
||||
- Install the requirements: `pip install -r requirements.txt`
|
||||
- Install the development requirements: `pip install -r requirements-dev.txt`
|
||||
- Install the development requirements: `pip install -r dev_requirements.txt`
|
||||
- Install osxphotos: `pip install -e .`
|
||||
|
||||
## Running tests
|
||||
|
||||
9
build.sh
9
build.sh
@@ -12,6 +12,7 @@ cog -d -o osxphotos/phototemplate.md osxphotos/phototemplate.cog.md
|
||||
|
||||
echo "Updating README.md"
|
||||
python3 utils/update_readme.py
|
||||
cog -r README.md
|
||||
|
||||
echo "Updating API_README.md"
|
||||
cog -r API_README.md
|
||||
@@ -29,6 +30,12 @@ python3 utils/generate_template_docs.py
|
||||
m2r2 docsrc/source/template_help.md
|
||||
rm docsrc/source/template_help.md
|
||||
|
||||
echo "Copying API_README.md to docsrc/source/api_readme.md"
|
||||
rm docsrc/source/api_readme.rst
|
||||
cp API_README.md docsrc/source/api_readme.md
|
||||
m2r2 docsrc/source/api_readme.md
|
||||
rm docsrc/source/api_readme.md
|
||||
|
||||
# build docs
|
||||
echo "Building docs"
|
||||
(cd docsrc && make github && make pdf)
|
||||
@@ -53,4 +60,4 @@ ARCHSTR=$(uname -m)
|
||||
ZIPNAME=osxphotos_MacOS_exe_darwin_${ARCHSTR}_v${OSXPHOTOSVERSION}.zip
|
||||
echo "Zipping CLI executable to $ZIPNAME"
|
||||
cd dist && zip $ZIPNAME osxphotos && cd ..
|
||||
rm dist/osxphotos
|
||||
rm dist/osxphotos
|
||||
|
||||
@@ -2,7 +2,7 @@ build
|
||||
bump2version==1.0.1
|
||||
cogapp>=3.3.0,<4.0.0
|
||||
furo
|
||||
m2r2==0.3.3
|
||||
m2r2==0.3.3.post2
|
||||
pdbpp
|
||||
pyinstaller==5.6.2
|
||||
pytest-cov==4.0.0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Sphinx build info version 1
|
||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: 2b1d245eff1c1e7c9d89e31092ea013b
|
||||
config: b13e33299efc7bf921ed35d6fb356cb4
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
|
||||
3457
docs/API_README.html
Normal file
3457
docs/API_README.html
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../genindex.html" /><link rel="search" title="Search" href="../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>Overview: module code - osxphotos 0.56.2 documentation</title>
|
||||
<title>Overview: module code - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css" />
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../index.html"><div class="brand">osxphotos 0.56.2 documentation</div></a>
|
||||
<a href="../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.56.2 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,8 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../api_readme.html">OSXPhotos Python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos._constants - osxphotos 0.55.7 documentation</title>
|
||||
<title>osxphotos._constants - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.55.7 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.55.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -195,14 +195,18 @@
|
||||
</div>
|
||||
<article role="main">
|
||||
<h1>Source code for osxphotos._constants</h1><div class="highlight"><pre>
|
||||
<span></span><span class="sd">"""</span>
|
||||
<span class="sd">Constants used by osxphotos </span>
|
||||
<span class="sd">"""</span>
|
||||
<span></span><span class="sd">""" Constants used by osxphotos """</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">annotations</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">logging</span>
|
||||
<span class="kn">import</span> <span class="nn">os.path</span>
|
||||
<span class="kn">import</span> <span class="nn">sqlite3</span>
|
||||
<span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span>
|
||||
<span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">Enum</span>
|
||||
|
||||
<span class="n">logger</span><span class="p">:</span> <span class="n">logging</span><span class="o">.</span><span class="n">Logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s2">"osxphotos"</span><span class="p">)</span>
|
||||
|
||||
<span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">"osxphotos"</span>
|
||||
|
||||
<span class="n">OSXPHOTOS_URL</span> <span class="o">=</span> <span class="s2">"https://github.com/RhetTbull/osxphotos"</span>
|
||||
@@ -211,23 +215,23 @@
|
||||
<span class="c1"># Apple Epoch is Jan 1, 2001</span>
|
||||
<span class="n">TIME_DELTA</span> <span class="o">=</span> <span class="p">(</span><span class="n">datetime</span><span class="p">(</span><span class="mi">2001</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-</span> <span class="n">datetime</span><span class="p">(</span><span class="mi">1970</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span><span class="o">.</span><span class="n">total_seconds</span><span class="p">()</span>
|
||||
|
||||
<span class="c1"># Unicode format to use for comparing strings</span>
|
||||
<span class="n">UNICODE_FORMAT</span> <span class="o">=</span> <span class="s2">"NFC"</span>
|
||||
|
||||
<span class="c1"># which Photos library database versions have been tested</span>
|
||||
<span class="c1"># Photos 2.0 (10.12.6) == 2622</span>
|
||||
<span class="c1"># Photos 3.0 (10.13.6) == 3301</span>
|
||||
<span class="c1"># Photos 4.0 (10.14.5) == 4016</span>
|
||||
<span class="c1"># Photos 4.0 (10.14.6) == 4025</span>
|
||||
<span class="c1"># Photos 5.0 (10.15.0) == 6000 or 5001</span>
|
||||
<span class="c1"># Photos 5.0+ (10.15.0) == 6000 or 5001</span>
|
||||
<span class="n">_TESTED_DB_VERSIONS</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"6000"</span><span class="p">,</span> <span class="s2">"5001"</span><span class="p">,</span> <span class="s2">"4025"</span><span class="p">,</span> <span class="s2">"4016"</span><span class="p">,</span> <span class="s2">"3301"</span><span class="p">,</span> <span class="s2">"2622"</span><span class="p">]</span>
|
||||
|
||||
<span class="c1"># database model versions (applies to Photos 5, Photos 6)</span>
|
||||
<span class="c1"># database model versions (applies to Photos 5+)</span>
|
||||
<span class="c1"># these come from PLModelVersion key in binary plist in Z_METADATA.Z_PLIST</span>
|
||||
<span class="c1"># Photos 5 (10.15.1) == 13537</span>
|
||||
<span class="c1"># Photos 5 (10.15.4, 10.15.5, 10.15.6) == 13703</span>
|
||||
<span class="c1"># Photos 6 (10.16.0 Beta) == 14104</span>
|
||||
<span class="n">_TEST_MODEL_VERSIONS</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"13537"</span><span class="p">,</span> <span class="s2">"13703"</span><span class="p">,</span> <span class="s2">"14104"</span><span class="p">]</span>
|
||||
<span class="c1"># Photos 7 (12.0.1) == 15323</span>
|
||||
<span class="c1"># Photos 8 (13.0.0) == 16320</span>
|
||||
<span class="c1"># Photos 9 (14.0.0 dev preview) = 17120</span>
|
||||
<span class="n">_TEST_MODEL_VERSIONS</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"13537"</span><span class="p">,</span> <span class="s2">"13703"</span><span class="p">,</span> <span class="s2">"14104"</span><span class="p">,</span> <span class="s2">"15323"</span><span class="p">,</span> <span class="s2">"16320"</span><span class="p">,</span> <span class="s2">"17120"</span><span class="p">]</span>
|
||||
|
||||
<span class="n">_PHOTOS_2_VERSION</span> <span class="o">=</span> <span class="s2">"2622"</span>
|
||||
|
||||
@@ -235,7 +239,7 @@
|
||||
<span class="n">_PHOTOS_3_VERSION</span> <span class="o">=</span> <span class="s2">"3301"</span>
|
||||
|
||||
<span class="c1"># versions 5.0 and later have a different database structure</span>
|
||||
<span class="n">_PHOTOS_4_VERSION</span> <span class="o">=</span> <span class="s2">"4025"</span> <span class="c1"># latest Mojove version on 10.14.6</span>
|
||||
<span class="n">_PHOTOS_4_VERSION</span> <span class="o">=</span> <span class="s2">"4025"</span> <span class="c1"># latest Mojave version on 10.14.6</span>
|
||||
<span class="n">_PHOTOS_5_VERSION</span> <span class="o">=</span> <span class="s2">"5000"</span> <span class="c1"># I've seen both 5001 and 6000. 6000 is most common on Catalina and up but there are some version 5001 database in the wild</span>
|
||||
|
||||
<span class="c1"># Ranges for model version by Photos version</span>
|
||||
@@ -243,8 +247,12 @@
|
||||
<span class="n">_PHOTOS_6_MODEL_VERSION</span> <span class="o">=</span> <span class="p">[</span><span class="mi">14000</span><span class="p">,</span> <span class="mi">14999</span><span class="p">]</span>
|
||||
<span class="n">_PHOTOS_7_MODEL_VERSION</span> <span class="o">=</span> <span class="p">[</span><span class="mi">15000</span><span class="p">,</span> <span class="mi">15999</span><span class="p">]</span> <span class="c1"># Dev preview: 15134, 12.1: 15331</span>
|
||||
<span class="n">_PHOTOS_8_MODEL_VERSION</span> <span class="o">=</span> <span class="p">[</span><span class="mi">16000</span><span class="p">,</span> <span class="mi">16999</span><span class="p">]</span> <span class="c1"># Ventura dev preview: 16119</span>
|
||||
<span class="n">_PHOTOS_9_MODEL_VERSION</span> <span class="o">=</span> <span class="p">[</span><span class="mi">17000</span><span class="p">,</span> <span class="mi">17999</span><span class="p">]</span> <span class="c1"># Sonoma dev preview: 17120</span>
|
||||
|
||||
<span class="c1"># some table names differ between Photos 5 and Photos 6</span>
|
||||
<span class="c1"># the preview versions of 12.0.0 had a difference schema for syndication info so need to check model version before processing</span>
|
||||
<span class="n">_PHOTOS_SYNDICATION_MODEL_VERSION</span> <span class="o">=</span> <span class="mi">15323</span> <span class="c1"># 12.0.1</span>
|
||||
|
||||
<span class="c1"># some table names differ between Photos 5 and later versions</span>
|
||||
<span class="n">_DB_TABLE_NAMES</span> <span class="o">=</span> <span class="p">{</span>
|
||||
<span class="mi">5</span><span class="p">:</span> <span class="p">{</span>
|
||||
<span class="s2">"ASSET"</span><span class="p">:</span> <span class="s2">"ZGENERICASSET"</span><span class="p">,</span>
|
||||
@@ -257,6 +265,8 @@
|
||||
<span class="s2">"ASSET_ALBUM_JOIN"</span><span class="p">:</span> <span class="s2">"Z_26ASSETS.Z_26ALBUMS"</span><span class="p">,</span>
|
||||
<span class="s2">"ASSET_ALBUM_TABLE"</span><span class="p">:</span> <span class="s2">"Z_26ASSETS"</span><span class="p">,</span>
|
||||
<span class="s2">"HDR_TYPE"</span><span class="p">:</span> <span class="s2">"ZCUSTOMRENDEREDVALUE"</span><span class="p">,</span>
|
||||
<span class="s2">"DETECTED_FACE_PERSON_FK"</span><span class="p">:</span> <span class="s2">"ZDETECTEDFACE.ZPERSON"</span><span class="p">,</span>
|
||||
<span class="s2">"DETECTED_FACE_ASSET_FK"</span><span class="p">:</span> <span class="s2">"ZDETECTEDFACE.ZASSET"</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="mi">6</span><span class="p">:</span> <span class="p">{</span>
|
||||
<span class="s2">"ASSET"</span><span class="p">:</span> <span class="s2">"ZASSET"</span><span class="p">,</span>
|
||||
@@ -269,6 +279,8 @@
|
||||
<span class="s2">"ASSET_ALBUM_JOIN"</span><span class="p">:</span> <span class="s2">"Z_26ASSETS.Z_26ALBUMS"</span><span class="p">,</span>
|
||||
<span class="s2">"ASSET_ALBUM_TABLE"</span><span class="p">:</span> <span class="s2">"Z_26ASSETS"</span><span class="p">,</span>
|
||||
<span class="s2">"HDR_TYPE"</span><span class="p">:</span> <span class="s2">"ZCUSTOMRENDEREDVALUE"</span><span class="p">,</span>
|
||||
<span class="s2">"DETECTED_FACE_PERSON_FK"</span><span class="p">:</span> <span class="s2">"ZDETECTEDFACE.ZPERSON"</span><span class="p">,</span>
|
||||
<span class="s2">"DETECTED_FACE_ASSET_FK"</span><span class="p">:</span> <span class="s2">"ZDETECTEDFACE.ZASSET"</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="mi">7</span><span class="p">:</span> <span class="p">{</span>
|
||||
<span class="s2">"ASSET"</span><span class="p">:</span> <span class="s2">"ZASSET"</span><span class="p">,</span>
|
||||
@@ -281,6 +293,8 @@
|
||||
<span class="s2">"ASSET_ALBUM_JOIN"</span><span class="p">:</span> <span class="s2">"Z_27ASSETS.Z_27ALBUMS"</span><span class="p">,</span>
|
||||
<span class="s2">"ASSET_ALBUM_TABLE"</span><span class="p">:</span> <span class="s2">"Z_27ASSETS"</span><span class="p">,</span>
|
||||
<span class="s2">"HDR_TYPE"</span><span class="p">:</span> <span class="s2">"ZHDRTYPE"</span><span class="p">,</span>
|
||||
<span class="s2">"DETECTED_FACE_PERSON_FK"</span><span class="p">:</span> <span class="s2">"ZDETECTEDFACE.ZPERSON"</span><span class="p">,</span>
|
||||
<span class="s2">"DETECTED_FACE_ASSET_FK"</span><span class="p">:</span> <span class="s2">"ZDETECTEDFACE.ZASSET"</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="mi">8</span><span class="p">:</span> <span class="p">{</span>
|
||||
<span class="s2">"ASSET"</span><span class="p">:</span> <span class="s2">"ZASSET"</span><span class="p">,</span>
|
||||
@@ -293,6 +307,22 @@
|
||||
<span class="s2">"ASSET_ALBUM_JOIN"</span><span class="p">:</span> <span class="s2">"Z_28ASSETS.Z_28ALBUMS"</span><span class="p">,</span>
|
||||
<span class="s2">"ASSET_ALBUM_TABLE"</span><span class="p">:</span> <span class="s2">"Z_28ASSETS"</span><span class="p">,</span>
|
||||
<span class="s2">"HDR_TYPE"</span><span class="p">:</span> <span class="s2">"ZHDRTYPE"</span><span class="p">,</span>
|
||||
<span class="s2">"DETECTED_FACE_PERSON_FK"</span><span class="p">:</span> <span class="s2">"ZDETECTEDFACE.ZPERSON"</span><span class="p">,</span>
|
||||
<span class="s2">"DETECTED_FACE_ASSET_FK"</span><span class="p">:</span> <span class="s2">"ZDETECTEDFACE.ZASSET"</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="mi">9</span><span class="p">:</span> <span class="p">{</span>
|
||||
<span class="s2">"ASSET"</span><span class="p">:</span> <span class="s2">"ZASSET"</span><span class="p">,</span>
|
||||
<span class="s2">"KEYWORD_JOIN"</span><span class="p">:</span> <span class="s2">"Z_1KEYWORDS.Z_40KEYWORDS"</span><span class="p">,</span>
|
||||
<span class="s2">"ALBUM_JOIN"</span><span class="p">:</span> <span class="s2">"Z_28ASSETS.Z_3ASSETS"</span><span class="p">,</span>
|
||||
<span class="s2">"ALBUM_SORT_ORDER"</span><span class="p">:</span> <span class="s2">"Z_28ASSETS.Z_FOK_3ASSETS"</span><span class="p">,</span>
|
||||
<span class="s2">"IMPORT_FOK"</span><span class="p">:</span> <span class="s2">"null"</span><span class="p">,</span>
|
||||
<span class="s2">"DEPTH_STATE"</span><span class="p">:</span> <span class="s2">"ZASSET.ZDEPTHTYPE"</span><span class="p">,</span>
|
||||
<span class="s2">"UTI_ORIGINAL"</span><span class="p">:</span> <span class="s2">"ZINTERNALRESOURCE.ZCOMPACTUTI"</span><span class="p">,</span>
|
||||
<span class="s2">"ASSET_ALBUM_JOIN"</span><span class="p">:</span> <span class="s2">"Z_28ASSETS.Z_28ALBUMS"</span><span class="p">,</span>
|
||||
<span class="s2">"ASSET_ALBUM_TABLE"</span><span class="p">:</span> <span class="s2">"Z_28ASSETS"</span><span class="p">,</span>
|
||||
<span class="s2">"HDR_TYPE"</span><span class="p">:</span> <span class="s2">"ZHDRTYPE"</span><span class="p">,</span>
|
||||
<span class="s2">"DETECTED_FACE_PERSON_FK"</span><span class="p">:</span> <span class="s2">"ZDETECTEDFACE.ZPERSONFORFACE"</span><span class="p">,</span>
|
||||
<span class="s2">"DETECTED_FACE_ASSET_FK"</span><span class="p">:</span> <span class="s2">"ZDETECTEDFACE.ZASSETFORFACE"</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
@@ -320,6 +350,10 @@
|
||||
<span class="p">(</span><span class="s2">"12"</span><span class="p">,</span> <span class="s2">"6"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"13"</span><span class="p">,</span> <span class="s2">"0"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"13"</span><span class="p">,</span> <span class="s2">"1"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"13"</span><span class="p">,</span> <span class="s2">"2"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"13"</span><span class="p">,</span> <span class="s2">"3"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"13"</span><span class="p">,</span> <span class="s2">"4"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"14"</span><span class="p">,</span> <span class="s2">"0"</span><span class="p">),</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="c1"># Photos 5 has persons who are empty string if unidentified face</span>
|
||||
@@ -335,7 +369,9 @@
|
||||
<span class="n">_PHOTOS_8_SHARED_PHOTO_PATH</span> <span class="o">=</span> <span class="s2">"scopes/cloudsharing/data"</span>
|
||||
|
||||
<span class="c1"># Where are shared iCloud derivatives located?</span>
|
||||
<span class="n">_PHOTOS_5_SHARED_DERIVATIVE_PATH</span> <span class="o">=</span> <span class="s2">"resources/cloudsharing/resources/derivatives/masters"</span>
|
||||
<span class="n">_PHOTOS_5_SHARED_DERIVATIVE_PATH</span> <span class="o">=</span> <span class="p">(</span>
|
||||
<span class="s2">"resources/cloudsharing/resources/derivatives/masters"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">_PHOTOS_8_SHARED_DERIVATIVE_PATH</span> <span class="o">=</span> <span class="s2">"scopes/cloudsharing/resources/derivatives/masters"</span>
|
||||
|
||||
<span class="c1"># What type of file? Based on ZGENERICASSET.ZKIND in Photos 5 database</span>
|
||||
@@ -375,6 +411,9 @@
|
||||
<span class="c1"># If anyone has a keyword matching this, then too bad...</span>
|
||||
<span class="n">_OSXPHOTOS_NONE_SENTINEL</span> <span class="o">=</span> <span class="s2">"OSXPhotosXYZZY42_Sentinel$"</span>
|
||||
|
||||
<span class="c1"># Lock file extension for reserving filenames when exporting</span>
|
||||
<span class="n">_OSXPHOTOS_LOCK_EXTENSION</span> <span class="o">=</span> <span class="s2">".osxphotos.lock"</span>
|
||||
|
||||
|
||||
<span class="k">class</span> <span class="nc">SearchCategory</span><span class="p">:</span>
|
||||
<span class="sd">"""SearchInfo categories for Photos 5+; corresponds to categories in database/search/psi.sqlite:groups.category</span>
|
||||
@@ -410,11 +449,11 @@
|
||||
<span class="n">TITLE</span> <span class="o">=</span> <span class="mi">2017</span>
|
||||
<span class="n">DESCRIPTION</span> <span class="o">=</span> <span class="mi">2018</span>
|
||||
<span class="n">HOME</span> <span class="o">=</span> <span class="mi">2020</span>
|
||||
<span class="n">WORK</span> <span class="o">=</span> <span class="mi">2036</span>
|
||||
<span class="n">PERSON</span> <span class="o">=</span> <span class="mi">2021</span>
|
||||
<span class="n">ACTIVITY</span> <span class="o">=</span> <span class="mi">2027</span>
|
||||
<span class="n">HOLIDAY</span> <span class="o">=</span> <span class="mi">2029</span>
|
||||
<span class="n">SEASON</span> <span class="o">=</span> <span class="mi">2030</span>
|
||||
<span class="n">WORK</span> <span class="o">=</span> <span class="mi">2036</span>
|
||||
<span class="n">VENUE</span> <span class="o">=</span> <span class="mi">2038</span>
|
||||
<span class="n">VENUE_TYPE</span> <span class="o">=</span> <span class="mi">2039</span>
|
||||
<span class="n">PHOTO_TYPE_VIDEO</span> <span class="o">=</span> <span class="mi">2044</span>
|
||||
@@ -427,6 +466,7 @@
|
||||
<span class="n">PHOTO_TYPE_PORTRAIT</span> <span class="o">=</span> <span class="mi">2053</span>
|
||||
<span class="n">PHOTO_TYPE_SELFIES</span> <span class="o">=</span> <span class="mi">2054</span>
|
||||
<span class="n">PHOTO_TYPE_FAVORITES</span> <span class="o">=</span> <span class="mi">2055</span>
|
||||
<span class="n">PHOTO_TYPE_ANIMATED</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Photos 8+ only</span>
|
||||
<span class="n">MEDIA_TYPES</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="n">PHOTO_TYPE_VIDEO</span><span class="p">,</span>
|
||||
<span class="n">PHOTO_TYPE_SLOMO</span><span class="p">,</span>
|
||||
@@ -441,7 +481,23 @@
|
||||
<span class="p">]</span>
|
||||
<span class="n">PHOTO_NAME</span> <span class="o">=</span> <span class="mi">2056</span>
|
||||
<span class="n">CAMERA</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Photos 8+ only</span>
|
||||
<span class="n">TEXT_FOUND</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Photos 8+ only</span>
|
||||
<span class="n">DETECTED_TEXT</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Photos 8+ only</span>
|
||||
<span class="n">SOURCE</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Photos 8+ only</span>
|
||||
|
||||
<span class="nd">@classmethod</span>
|
||||
<span class="k">def</span> <span class="nf">categories</span><span class="p">(</span><span class="bp">cls</span><span class="p">)</span> <span class="o">-></span> <span class="nb">dict</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="nb">str</span><span class="p">]:</span>
|
||||
<span class="sd">"""Return categories as dict of value: name"""</span>
|
||||
<span class="c1"># a bit of a hack to basically reverse the enum</span>
|
||||
<span class="k">return</span> <span class="p">{</span>
|
||||
<span class="n">value</span><span class="p">:</span> <span class="n">name</span>
|
||||
<span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="n">name</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
||||
<span class="ow">and</span> <span class="ow">not</span> <span class="n">name</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"__"</span><span class="p">)</span>
|
||||
<span class="ow">and</span> <span class="ow">not</span> <span class="n">callable</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
|
||||
<span class="ow">and</span> <span class="n">name</span><span class="o">.</span><span class="n">isupper</span><span class="p">()</span>
|
||||
<span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="p">(</span><span class="nb">list</span><span class="p">,</span> <span class="nb">dict</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">))</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
|
||||
<span class="k">class</span> <span class="nc">SearchCategory_Photos8</span><span class="p">(</span><span class="n">SearchCategory</span><span class="p">):</span>
|
||||
@@ -449,6 +505,20 @@
|
||||
|
||||
<span class="c1"># Many of the category values changed in Ventura / Photos 8</span>
|
||||
<span class="c1"># and some new categories were added</span>
|
||||
<span class="n">CITY</span> <span class="o">=</span> <span class="mi">5</span>
|
||||
<span class="n">LOCALITY_4</span> <span class="o">=</span> <span class="mi">4</span>
|
||||
<span class="n">SUB_LOCALITY_5</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">SUB_LOCALITY_6</span> <span class="o">=</span> <span class="mi">6</span>
|
||||
<span class="n">LOCALITY_8</span> <span class="o">=</span> <span class="mi">8</span>
|
||||
<span class="n">NAMED_AREA</span> <span class="o">=</span> <span class="mi">7</span>
|
||||
<span class="n">ALL_LOCALITY</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="n">LOCALITY_4</span><span class="p">,</span>
|
||||
<span class="n">SUB_LOCALITY_6</span><span class="p">,</span>
|
||||
<span class="n">LOCALITY_8</span><span class="p">,</span>
|
||||
<span class="n">NAMED_AREA</span><span class="p">,</span>
|
||||
<span class="p">]</span>
|
||||
<span class="n">HOME</span> <span class="o">=</span> <span class="mi">1000</span>
|
||||
<span class="n">WORK</span> <span class="o">=</span> <span class="mi">1001</span>
|
||||
<span class="n">LABEL</span> <span class="o">=</span> <span class="mi">1500</span>
|
||||
<span class="n">MONTH</span> <span class="o">=</span> <span class="mi">1100</span>
|
||||
<span class="n">YEAR</span> <span class="o">=</span> <span class="mi">1101</span>
|
||||
@@ -458,11 +528,55 @@
|
||||
<span class="n">TITLE</span> <span class="o">=</span> <span class="mi">1201</span>
|
||||
<span class="n">DESCRIPTION</span> <span class="o">=</span> <span class="mi">1202</span>
|
||||
<span class="n">DETECTED_TEXT</span> <span class="o">=</span> <span class="mi">1203</span> <span class="c1"># new in Photos 8</span>
|
||||
<span class="n">TEXT_FOUND</span> <span class="o">=</span> <span class="mi">1205</span> <span class="c1"># new in Photos 8</span>
|
||||
<span class="n">PERSON</span> <span class="o">=</span> <span class="mi">1300</span>
|
||||
<span class="n">ACTIVITY</span> <span class="o">=</span> <span class="mi">1600</span>
|
||||
<span class="n">VENUE</span> <span class="o">=</span> <span class="mi">1700</span>
|
||||
<span class="n">VENUE_TYPE</span> <span class="o">=</span> <span class="mi">1701</span>
|
||||
<span class="n">PHOTO_TYPE_VIDEO</span> <span class="o">=</span> <span class="mi">1901</span>
|
||||
<span class="n">PHOTO_TYPE_SELFIES</span> <span class="o">=</span> <span class="mi">1915</span>
|
||||
<span class="n">PHOTO_TYPE_LIVE</span> <span class="o">=</span> <span class="mi">1906</span>
|
||||
<span class="n">PHOTO_TYPE_PORTRAIT</span> <span class="o">=</span> <span class="mi">1914</span>
|
||||
<span class="n">PHOTO_TYPE_FAVORITES</span> <span class="o">=</span> <span class="mi">2000</span>
|
||||
<span class="n">PHOTO_TYPE_PANORAMA</span> <span class="o">=</span> <span class="mi">1908</span>
|
||||
<span class="n">PHOTO_TYPE_TIMELAPSE</span> <span class="o">=</span> <span class="mi">1909</span>
|
||||
<span class="n">PHOTO_TYPE_SLOMO</span> <span class="o">=</span> <span class="mi">1905</span>
|
||||
<span class="n">PHOTO_TYPE_BURSTS</span> <span class="o">=</span> <span class="mi">1913</span>
|
||||
<span class="n">PHOTO_TYPE_SCREENSHOT</span> <span class="o">=</span> <span class="mi">1907</span>
|
||||
<span class="n">PHOTO_TYPE_ANIMATED</span> <span class="o">=</span> <span class="mi">1912</span>
|
||||
<span class="n">PHOTO_TYPE_RAW</span> <span class="o">=</span> <span class="mi">1902</span>
|
||||
<span class="n">MEDIA_TYPES</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="n">PHOTO_TYPE_VIDEO</span><span class="p">,</span>
|
||||
<span class="n">PHOTO_TYPE_SLOMO</span><span class="p">,</span>
|
||||
<span class="n">PHOTO_TYPE_LIVE</span><span class="p">,</span>
|
||||
<span class="n">PHOTO_TYPE_SCREENSHOT</span><span class="p">,</span>
|
||||
<span class="n">PHOTO_TYPE_PANORAMA</span><span class="p">,</span>
|
||||
<span class="n">PHOTO_TYPE_TIMELAPSE</span><span class="p">,</span>
|
||||
<span class="n">PHOTO_TYPE_BURSTS</span><span class="p">,</span>
|
||||
<span class="n">PHOTO_TYPE_PORTRAIT</span><span class="p">,</span>
|
||||
<span class="n">PHOTO_TYPE_SELFIES</span><span class="p">,</span>
|
||||
<span class="n">PHOTO_TYPE_FAVORITES</span><span class="p">,</span>
|
||||
<span class="n">PHOTO_TYPE_ANIMATED</span><span class="p">,</span>
|
||||
<span class="p">]</span>
|
||||
<span class="n">PHOTO_NAME</span> <span class="o">=</span> <span class="mi">2100</span>
|
||||
<span class="n">CAMERA</span> <span class="o">=</span> <span class="mi">2300</span> <span class="c1"># new in Photos 8</span>
|
||||
<span class="n">SOURCE</span> <span class="o">=</span> <span class="mi">2200</span> <span class="c1"># new in Photos 8, shows the app/software source for the photo, e.g. Messages, Safari, etc.</span>
|
||||
|
||||
<span class="nd">@classmethod</span>
|
||||
<span class="k">def</span> <span class="nf">categories</span><span class="p">(</span><span class="bp">cls</span><span class="p">)</span> <span class="o">-></span> <span class="nb">dict</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="nb">str</span><span class="p">]:</span>
|
||||
<span class="sd">"""Return categories as dict of value: name"""</span>
|
||||
<span class="c1"># need to get the categories from the base class and update with the new values</span>
|
||||
<span class="n">classdict</span> <span class="o">=</span> <span class="n">SearchCategory</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
|
||||
<span class="n">classdict</span> <span class="o">|=</span> <span class="bp">cls</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="p">{</span>
|
||||
<span class="n">value</span><span class="p">:</span> <span class="n">name</span>
|
||||
<span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">classdict</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="n">name</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
||||
<span class="ow">and</span> <span class="ow">not</span> <span class="n">name</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"__"</span><span class="p">)</span>
|
||||
<span class="ow">and</span> <span class="ow">not</span> <span class="n">callable</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
|
||||
<span class="ow">and</span> <span class="n">name</span><span class="o">.</span><span class="n">isupper</span><span class="p">()</span>
|
||||
<span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="p">(</span><span class="nb">list</span><span class="p">,</span> <span class="nb">dict</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">))</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">search_category_factory</span><span class="p">(</span><span class="n">version</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="n">SearchCategory</span><span class="p">:</span>
|
||||
@@ -471,7 +585,7 @@
|
||||
|
||||
|
||||
<span class="c1"># Max filename length on MacOS</span>
|
||||
<span class="n">MAX_FILENAME_LEN</span> <span class="o">=</span> <span class="mi">255</span>
|
||||
<span class="n">MAX_FILENAME_LEN</span> <span class="o">=</span> <span class="mi">255</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">_OSXPHOTOS_LOCK_EXTENSION</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># Max directory name length on MacOS</span>
|
||||
<span class="n">MAX_DIRNAME_LEN</span> <span class="o">=</span> <span class="mi">255</span>
|
||||
@@ -576,6 +690,19 @@
|
||||
<span class="s2">"time"</span><span class="p">,</span>
|
||||
<span class="s2">"tottime"</span><span class="p">,</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="n">UUID_PATTERN</span> <span class="o">=</span> <span class="p">(</span>
|
||||
<span class="sa">r</span><span class="s2">"[0-9a-fA-F]</span><span class="si">{8}</span><span class="s2">-[0-9a-fA-F]</span><span class="si">{4}</span><span class="s2">-[0-9a-fA-F]</span><span class="si">{4}</span><span class="s2">-[0-9a-fA-F]</span><span class="si">{4}</span><span class="s2">-[0-9a-fA-F]</span><span class="si">{12}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="c1"># Reference: https://docs.python.org/3/library/sqlite3.html?highlight=sqlite3%20threadsafety#sqlite3.threadsafety</span>
|
||||
<span class="c1"># and https://docs.python.org/3/library/sqlite3.html?highlight=sqlite3%20threadsafety#sqlite3.connect</span>
|
||||
<span class="c1"># 3: serialized mode; Threads may share the module, connections and cursors</span>
|
||||
<span class="c1"># 3 is the default in the python.org python 3.11 distribution</span>
|
||||
<span class="c1"># earlier versions of python.org python 3.x default to 1 which means threads may not share</span>
|
||||
<span class="c1"># sqlite3 connections and thus PhotoInfo.export() cannot be used in a multithreaded environment</span>
|
||||
<span class="c1"># pass SQLITE_CHECK_SAME_THREAD to sqlite3.connect() to enable multithreaded access on systems that support it</span>
|
||||
<span class="n">SQLITE_CHECK_SAME_THREAD</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">threadsafety</span> <span class="o">==</span> <span class="mi">3</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">SQLITE_CHECK_SAME_THREAD</span><span class="si">=}</span><span class="s2">, </span><span class="si">{</span><span class="n">sqlite3</span><span class="o">.</span><span class="n">threadsafety</span><span class="si">=}</span><span class="s2">"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.albuminfo - osxphotos 0.54.1 documentation</title>
|
||||
<title>osxphotos.albuminfo - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.54.1 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.1 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -215,6 +215,7 @@
|
||||
<span class="n">_PHOTOS_4_VERSION</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_5_ALBUM_KIND</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_5_FOLDER_KIND</span><span class="p">,</span>
|
||||
<span class="n">_PHOTOS_5_VERSION</span><span class="p">,</span>
|
||||
<span class="n">TIME_DELTA</span><span class="p">,</span>
|
||||
<span class="n">AlbumSortOrder</span><span class="p">,</span>
|
||||
<span class="p">)</span>
|
||||
@@ -246,9 +247,8 @@
|
||||
<span class="sd"> ValueError: raised if len(values) != len(sort_keys)</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">values</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="n">sort_keys</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"values and sort_keys must have same length"</span><span class="p">)</span>
|
||||
|
||||
<span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="nb">sorted</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">sort_keys</span><span class="p">,</span> <span class="n">values</span><span class="p">))))[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"values and sort_keys must be same length"</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="p">[</span><span class="n">x</span> <span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">sort_keys</span><span class="p">,</span> <span class="n">values</span><span class="p">))]</span>
|
||||
|
||||
|
||||
<span class="k">class</span> <span class="nc">AlbumInfoBaseClass</span><span class="p">:</span>
|
||||
@@ -258,7 +258,7 @@
|
||||
<span class="sd"> including folders, photos, etc.</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">db</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">uuid</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">db</span><span class="p">,</span> <span class="n">uuid</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_uuid</span> <span class="o">=</span> <span class="n">uuid</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_db</span> <span class="o">=</span> <span class="n">db</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_title</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">_dbalbum_details</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"title"</span><span class="p">]</span>
|
||||
@@ -318,7 +318,8 @@
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">end_date</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""For Albums, return end date (most recent image) of album or None for albums with no images</span>
|
||||
<span class="sd"> For Import Sessions, return end date of import sessions (when import was completed)"""</span>
|
||||
<span class="sd"> For Import Sessions, return end date of import sessions (when import was completed)</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_end_date</span>
|
||||
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
|
||||
@@ -360,6 +361,16 @@
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_owner</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_owner</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return album info as a dict; does not include photos"""</span>
|
||||
<span class="k">return</span> <span class="p">{</span>
|
||||
<span class="s2">"uuid"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="p">,</span>
|
||||
<span class="s2">"creation_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">creation_date</span><span class="p">,</span>
|
||||
<span class="s2">"start_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">start_date</span><span class="p">,</span>
|
||||
<span class="s2">"end_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">end_date</span><span class="p">,</span>
|
||||
<span class="s2">"owner"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">owner</span><span class="p">,</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""return number of photos contained in album"""</span>
|
||||
<span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photos</span><span class="p">)</span>
|
||||
@@ -371,6 +382,10 @@
|
||||
<span class="sd"> including folders, photos, etc.</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">db</span><span class="p">,</span> <span class="n">uuid</span><span class="p">):</span>
|
||||
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">db</span><span class="o">=</span><span class="n">db</span><span class="p">,</span> <span class="n">uuid</span><span class="o">=</span><span class="n">uuid</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_title</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">_dbalbum_details</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"title"</span><span class="p">]</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">title</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""return title / name of album"""</span>
|
||||
@@ -402,10 +417,11 @@
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">folder_names</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""return hierarchical list of folders the album is contained in</span>
|
||||
<span class="sd">"""Return hierarchical list of folders the album is contained in</span>
|
||||
<span class="sd"> the folder list is in form:</span>
|
||||
<span class="sd"> ["Top level folder", "sub folder 1", "sub folder 2", ...]</span>
|
||||
<span class="sd"> returns empty list if album is not in any folders"""</span>
|
||||
<span class="sd"> or empty list if album is not in any folders</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_folder_names</span>
|
||||
@@ -415,10 +431,9 @@
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">folder_list</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""return hierarchical list of folders the album is contained in</span>
|
||||
<span class="sd"> as list of FolderInfo objects in form</span>
|
||||
<span class="sd"> ["Top level folder", "sub folder 1", "sub folder 2", ...]</span>
|
||||
<span class="sd"> returns empty list if album is not in any folders"""</span>
|
||||
<span class="sd">"""Returns list of FolderInfo objects for each folder the album is contained in</span>
|
||||
<span class="sd"> or empty list if album is not in any folders</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_folders</span>
|
||||
@@ -443,7 +458,7 @@
|
||||
<span class="n">parent_pk</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">_dbalbum_details</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_uuid</span><span class="p">][</span><span class="s2">"parentfolder"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_parent</span> <span class="o">=</span> <span class="p">(</span>
|
||||
<span class="n">FolderInfo</span><span class="p">(</span><span class="n">db</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="p">,</span> <span class="n">uuid</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">_dbalbums_pk</span><span class="p">[</span><span class="n">parent_pk</span><span class="p">])</span>
|
||||
<span class="k">if</span> <span class="n">parent_pk</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">_folder_root_pk</span>
|
||||
<span class="k">if</span> <span class="n">parent_pk</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">parent_pk</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">_folder_root_pk</span>
|
||||
<span class="k">else</span> <span class="kc">None</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parent</span>
|
||||
@@ -476,29 +491,81 @@
|
||||
<span class="k">return</span> <span class="n">index</span>
|
||||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Photo with uuid </span><span class="si">{</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span><span class="si">}</span><span class="s2"> does not appear to be in this album"</span>
|
||||
<span class="p">)</span></div></div>
|
||||
<span class="p">)</span></div>
|
||||
|
||||
<div class="viewcode-block" id="AlbumInfo.asdict"><a class="viewcode-back" href="../../reference.html#osxphotos.AlbumInfo.asdict">[docs]</a> <span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return album info as a dict; does not include photos"""</span>
|
||||
<span class="n">dict_data</span> <span class="o">=</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">asdict</span><span class="p">()</span>
|
||||
<span class="n">dict_data</span><span class="p">[</span><span class="s2">"title"</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">dict_data</span><span class="p">[</span><span class="s2">"folder_names"</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">folder_names</span>
|
||||
<span class="n">dict_data</span><span class="p">[</span><span class="s2">"folder_list"</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">f</span><span class="o">.</span><span class="n">uuid</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">folder_list</span><span class="p">]</span>
|
||||
<span class="n">dict_data</span><span class="p">[</span><span class="s2">"sort_order"</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">sort_order</span>
|
||||
<span class="n">dict_data</span><span class="p">[</span><span class="s2">"parent"</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">uuid</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">parent</span> <span class="k">else</span> <span class="kc">None</span>
|
||||
<span class="k">return</span> <span class="n">dict_data</span></div></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="ImportInfo"><a class="viewcode-back" href="../../reference.html#osxphotos.ImportInfo">[docs]</a><span class="k">class</span> <span class="nc">ImportInfo</span><span class="p">(</span><span class="n">AlbumInfoBaseClass</span><span class="p">):</span>
|
||||
<span class="sd">"""Information about import sessions"""</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">db</span><span class="p">,</span> <span class="n">uuid</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_uuid</span> <span class="o">=</span> <span class="n">uuid</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_db</span> <span class="o">=</span> <span class="n">db</span>
|
||||
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_db_version</span> <span class="o">>=</span> <span class="n">_PHOTOS_5_VERSION</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">db</span><span class="o">=</span><span class="n">db</span><span class="p">,</span> <span class="n">uuid</span><span class="o">=</span><span class="n">uuid</span><span class="p">)</span>
|
||||
|
||||
<span class="n">import_session</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_db_import_group</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_uuid</span><span class="p">]</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_creation_date_timestamp</span> <span class="o">=</span> <span class="n">import_session</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>
|
||||
<span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">,</span> <span class="ne">KeyError</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_creation_date_timestamp</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">(</span><span class="mi">1970</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_start_date_timestamp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_creation_date_timestamp</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_end_date_timestamp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_creation_date_timestamp</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_title</span> <span class="o">=</span> <span class="n">import_session</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_local_tz</span> <span class="o">=</span> <span class="n">get_local_tz</span><span class="p">(</span>
|
||||
<span class="n">datetime</span><span class="o">.</span><span class="n">fromtimestamp</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_creation_date_timestamp</span> <span class="o">+</span> <span class="n">TIME_DELTA</span><span class="p">)</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">title</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""return title / name of import session"""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_title</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">photos</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""return list of photos contained in import session"""</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photos</span>
|
||||
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
|
||||
<span class="n">uuid_list</span><span class="p">,</span> <span class="n">sort_order</span> <span class="o">=</span> <span class="nb">zip</span><span class="p">(</span>
|
||||
<span class="o">*</span><span class="p">[</span>
|
||||
<span class="p">(</span><span class="n">uuid</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"fok_import_session"</span><span class="p">])</span>
|
||||
<span class="k">for</span> <span class="n">uuid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbphotos</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"import_uuid"</span><span class="p">]</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_db_version</span> <span class="o">>=</span> <span class="n">_PHOTOS_5_VERSION</span><span class="p">:</span>
|
||||
<span class="n">uuid_list</span><span class="p">,</span> <span class="n">sort_order</span> <span class="o">=</span> <span class="nb">zip</span><span class="p">(</span>
|
||||
<span class="o">*</span><span class="p">[</span>
|
||||
<span class="p">(</span><span class="n">uuid</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"fok_import_session"</span><span class="p">])</span>
|
||||
<span class="k">for</span> <span class="n">uuid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbphotos</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"import_uuid"</span><span class="p">]</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span>
|
||||
<span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">sorted_uuid</span> <span class="o">=</span> <span class="n">sort_list_by_keys</span><span class="p">(</span><span class="n">uuid_list</span><span class="p">,</span> <span class="n">sort_order</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_photos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">photos_by_uuid</span><span class="p">(</span><span class="n">sorted_uuid</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">import_photo_uuids</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="n">u</span>
|
||||
<span class="k">for</span> <span class="n">u</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbphotos</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">u</span><span class="p">][</span><span class="s2">"import_uuid"</span><span class="p">]</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span>
|
||||
<span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">sorted_uuid</span> <span class="o">=</span> <span class="n">sort_list_by_keys</span><span class="p">(</span><span class="n">uuid_list</span><span class="p">,</span> <span class="n">sort_order</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_photos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">photos_by_uuid</span><span class="p">(</span><span class="n">sorted_uuid</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_photos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">photos_by_uuid</span><span class="p">(</span><span class="n">import_photo_uuids</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photos</span>
|
||||
|
||||
<div class="viewcode-block" id="ImportInfo.asdict"><a class="viewcode-back" href="../../reference.html#osxphotos.ImportInfo.asdict">[docs]</a> <span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return import info as a dict; does not include photos"""</span>
|
||||
<span class="k">return</span> <span class="p">{</span>
|
||||
<span class="s2">"uuid"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="p">,</span>
|
||||
<span class="s2">"creation_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">creation_date</span><span class="p">,</span>
|
||||
<span class="s2">"start_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">start_date</span><span class="p">,</span>
|
||||
<span class="s2">"end_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">end_date</span><span class="p">,</span>
|
||||
<span class="s2">"title"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">,</span>
|
||||
<span class="p">}</span></div>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__bool__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Always returns True</span>
|
||||
<span class="sd"> A photo without an import session will return None for import_info,</span>
|
||||
@@ -506,13 +573,32 @@
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">return</span> <span class="kc">True</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="ProjectInfo"><a class="viewcode-back" href="../../reference.html#osxphotos.ProjectInfo">[docs]</a><span class="k">class</span> <span class="nc">ProjectInfo</span><span class="p">(</span><span class="n">AlbumInfo</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ProjectInfo with info about projects</span>
|
||||
<span class="sd"> Projects are cards, calendars, slideshows, etc.</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="o">...</span></div>
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">folder_names</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return hierarchical list of folders the album is contained in</span>
|
||||
<span class="sd"> the folder list is in form:</span>
|
||||
<span class="sd"> ["Top level folder", "sub folder 1", "sub folder 2", ...]</span>
|
||||
<span class="sd"> or empty list if album is not in any folders</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="c1"># projects are not in folders</span>
|
||||
<span class="k">return</span> <span class="p">[]</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">folder_list</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns list of FolderInfo objects for each folder the album is contained in</span>
|
||||
<span class="sd"> or empty list if album is not in any folders</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="c1"># projects are not in folders</span>
|
||||
<span class="k">return</span> <span class="p">[]</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="FolderInfo"><a class="viewcode-back" href="../../reference.html#osxphotos.FolderInfo">[docs]</a><span class="k">class</span> <span class="nc">FolderInfo</span><span class="p">:</span>
|
||||
@@ -583,7 +669,7 @@
|
||||
<span class="n">parent_pk</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">_dbalbum_details</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_uuid</span><span class="p">][</span><span class="s2">"parentfolder"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_parent</span> <span class="o">=</span> <span class="p">(</span>
|
||||
<span class="n">FolderInfo</span><span class="p">(</span><span class="n">db</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="p">,</span> <span class="n">uuid</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">_dbalbums_pk</span><span class="p">[</span><span class="n">parent_pk</span><span class="p">])</span>
|
||||
<span class="k">if</span> <span class="n">parent_pk</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">_folder_root_pk</span>
|
||||
<span class="k">if</span> <span class="n">parent_pk</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">parent_pk</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">_folder_root_pk</span>
|
||||
<span class="k">else</span> <span class="kc">None</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parent</span>
|
||||
@@ -613,6 +699,16 @@
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_folders</span> <span class="o">=</span> <span class="n">folders</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_folders</span>
|
||||
|
||||
<div class="viewcode-block" id="FolderInfo.asdict"><a class="viewcode-back" href="../../reference.html#osxphotos.FolderInfo.asdict">[docs]</a> <span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return folder info as a dict"""</span>
|
||||
<span class="k">return</span> <span class="p">{</span>
|
||||
<span class="s2">"title"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">,</span>
|
||||
<span class="s2">"uuid"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="p">,</span>
|
||||
<span class="s2">"parent"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">uuid</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">parent</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"subfolders"</span><span class="p">:</span> <span class="p">[</span><span class="n">f</span><span class="o">.</span><span class="n">uuid</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">subfolders</span><span class="p">],</span>
|
||||
<span class="s2">"albums"</span><span class="p">:</span> <span class="p">[</span><span class="n">a</span><span class="o">.</span><span class="n">uuid</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">album_info</span><span class="p">],</span>
|
||||
<span class="p">}</span></div>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""returns count of folders + albums contained in the folder"""</span>
|
||||
<span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">subfolders</span><span class="p">)</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">album_info</span><span class="p">)</span></div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.debug - osxphotos 0.56.1 documentation</title>
|
||||
<title>osxphotos.debug - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.56.1 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.56.1 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -197,6 +197,8 @@
|
||||
<h1>Source code for osxphotos.debug</h1><div class="highlight"><pre>
|
||||
<span></span><span class="sd">"""Utilities for debugging"""</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">annotations</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">logging</span>
|
||||
<span class="kn">import</span> <span class="nn">sys</span>
|
||||
<span class="kn">import</span> <span class="nn">time</span>
|
||||
@@ -206,21 +208,33 @@
|
||||
<span class="kn">import</span> <span class="nn">wrapt</span>
|
||||
<span class="kn">from</span> <span class="nn">rich</span> <span class="kn">import</span> <span class="nb">print</span>
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="s2">"debug_breakpoint"</span><span class="p">,</span>
|
||||
<span class="s2">"debug_watch"</span><span class="p">,</span>
|
||||
<span class="s2">"get_debug_flags"</span><span class="p">,</span>
|
||||
<span class="s2">"get_debug_options"</span><span class="p">,</span>
|
||||
<span class="s2">"is_debug"</span><span class="p">,</span>
|
||||
<span class="s2">"set_debug"</span><span class="p">,</span>
|
||||
<span class="s2">"wrap_function"</span><span class="p">,</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
|
||||
<span class="c1"># global variable to control debug output</span>
|
||||
<span class="c1"># set via --debug</span>
|
||||
<span class="n">DEBUG</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
<span class="n">__osxphotos_debug</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="set_debug"><a class="viewcode-back" href="../../reference.html#osxphotos.set_debug">[docs]</a><span class="k">def</span> <span class="nf">set_debug</span><span class="p">(</span><span class="n">debug</span><span class="p">:</span> <span class="nb">bool</span><span class="p">):</span>
|
||||
<span class="sd">"""set debug flag"""</span>
|
||||
<span class="k">global</span> <span class="n">DEBUG</span>
|
||||
<span class="n">DEBUG</span> <span class="o">=</span> <span class="n">debug</span>
|
||||
<span class="k">global</span> <span class="n">__osxphotos_debug</span>
|
||||
<span class="n">__osxphotos_debug</span> <span class="o">=</span> <span class="n">debug</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">disable</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">NOTSET</span> <span class="k">if</span> <span class="n">debug</span> <span class="k">else</span> <span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="is_debug"><a class="viewcode-back" href="../../reference.html#osxphotos.is_debug">[docs]</a><span class="k">def</span> <span class="nf">is_debug</span><span class="p">():</span>
|
||||
<span class="sd">"""return debug flag"""</span>
|
||||
<span class="k">return</span> <span class="n">DEBUG</span></div>
|
||||
<span class="k">global</span> <span class="n">__osxphotos_debug</span>
|
||||
<span class="k">return</span> <span class="n">__osxphotos_debug</span></div>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">debug_watch</span><span class="p">(</span><span class="n">wrapped</span><span class="p">,</span> <span class="n">instance</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
|
||||
|
||||
@@ -1,36 +1,200 @@
|
||||
<!doctype html>
|
||||
<html class="no-js" lang="en">
|
||||
<head><meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<!DOCTYPE html>
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.exifinfo - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||
|
||||
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>osxphotos.exifinfo — osxphotos 0.47.9 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/alabaster.css" />
|
||||
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
|
||||
<script src="../../_static/jquery.js"></script>
|
||||
<script src="../../_static/underscore.js"></script>
|
||||
<script src="../../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../../genindex.html" />
|
||||
<link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<link rel="stylesheet" href="../../_static/custom.css" type="text/css" />
|
||||
|
||||
<style>
|
||||
body {
|
||||
--color-code-background: #f8f8f8;
|
||||
--color-code-foreground: black;
|
||||
|
||||
}
|
||||
@media not print {
|
||||
body[data-theme="dark"] {
|
||||
--color-code-background: #202020;
|
||||
--color-code-foreground: #d0d0d0;
|
||||
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body:not([data-theme="light"]) {
|
||||
--color-code-background: #202020;
|
||||
--color-code-foreground: #d0d0d0;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</style></head>
|
||||
<body>
|
||||
|
||||
<script>
|
||||
document.body.dataset.theme = localStorage.getItem("theme") || "auto";
|
||||
</script>
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||||
<symbol id="svg-toc" viewBox="0 0 24 24">
|
||||
<title>Contents</title>
|
||||
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 1024 1024">
|
||||
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM115.4 518.9L271.7 642c5.8 4.6 14.4.5 14.4-6.9V388.9c0-7.4-8.5-11.5-14.4-6.9L115.4 505.1a8.74 8.74 0 0 0 0 13.8z"/>
|
||||
</svg>
|
||||
</symbol>
|
||||
<symbol id="svg-menu" viewBox="0 0 24 24">
|
||||
<title>Menu</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-menu">
|
||||
<line x1="3" y1="12" x2="21" y2="12"></line>
|
||||
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="3" y1="18" x2="21" y2="18"></line>
|
||||
</svg>
|
||||
</symbol>
|
||||
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
|
||||
<title>Expand</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-chevron-right">
|
||||
<polyline points="9 18 15 12 9 6"></polyline>
|
||||
</svg>
|
||||
</symbol>
|
||||
<symbol id="svg-sun" viewBox="0 0 24 24">
|
||||
<title>Light mode</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather-sun">
|
||||
<circle cx="12" cy="12" r="5"></circle>
|
||||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||||
</svg>
|
||||
</symbol>
|
||||
<symbol id="svg-moon" viewBox="0 0 24 24">
|
||||
<title>Dark mode</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-moon">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" />
|
||||
</svg>
|
||||
</symbol>
|
||||
<symbol id="svg-sun-half" viewBox="0 0 24 24">
|
||||
<title>Auto light/dark mode</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-shadow">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<circle cx="12" cy="12" r="9" />
|
||||
<path d="M13 12h5" />
|
||||
<path d="M13 15h4" />
|
||||
<path d="M13 18h1" />
|
||||
<path d="M13 9h4" />
|
||||
<path d="M13 6h1" />
|
||||
</svg>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
||||
<input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation">
|
||||
<input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc">
|
||||
<label class="overlay sidebar-overlay" for="__navigation">
|
||||
<div class="visually-hidden">Hide navigation sidebar</div>
|
||||
</label>
|
||||
<label class="overlay toc-overlay" for="__toc">
|
||||
<div class="visually-hidden">Hide table of contents sidebar</div>
|
||||
</label>
|
||||
|
||||
|
||||
|
||||
<div class="page">
|
||||
<header class="mobile-header">
|
||||
<div class="header-left">
|
||||
<label class="nav-overlay-icon" for="__navigation">
|
||||
<div class="visually-hidden">Toggle site navigation sidebar</div>
|
||||
<i class="icon"><svg><use href="#svg-menu"></use></svg></i>
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
<button class="theme-toggle">
|
||||
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
|
||||
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||||
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
||||
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
|
||||
</button>
|
||||
</div>
|
||||
<label class="toc-overlay-icon toc-header-icon no-toc" for="__toc">
|
||||
<div class="visually-hidden">Toggle table of contents sidebar</div>
|
||||
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
|
||||
</label>
|
||||
</div>
|
||||
</header>
|
||||
<aside class="sidebar-drawer">
|
||||
<div class="sidebar-container">
|
||||
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
<input type="hidden" name="check_keywords" value="yes">
|
||||
<input type="hidden" name="area" value="default">
|
||||
</form>
|
||||
<div id="searchbox"></div><div class="sidebar-scroll"><div class="sidebar-tree">
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../overview.html">OSXPhotos</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../tutorial.html">OSXPhotos Tutorial</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<h1>Source code for osxphotos.exifinfo</h1><div class="highlight"><pre>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</aside>
|
||||
<div class="main">
|
||||
<div class="content">
|
||||
<div class="article-container">
|
||||
<a href="#" class="back-to-top muted-link">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z"></path>
|
||||
</svg>
|
||||
<span>Back to top</span>
|
||||
</a>
|
||||
<div class="content-icon-container">
|
||||
<div class="theme-toggle-container theme-toggle-content">
|
||||
<button class="theme-toggle">
|
||||
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
|
||||
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||||
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
||||
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
|
||||
</button>
|
||||
</div>
|
||||
<label class="toc-overlay-icon toc-content-icon no-toc" for="__toc">
|
||||
<div class="visually-hidden">Toggle table of contents sidebar</div>
|
||||
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
|
||||
</label>
|
||||
</div>
|
||||
<article role="main">
|
||||
<h1>Source code for osxphotos.exifinfo</h1><div class="highlight"><pre>
|
||||
<span></span><span class="sd">""" ExifInfo class to expose EXIF info from the library """</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span>
|
||||
@@ -62,72 +226,47 @@
|
||||
<span class="n">codec</span><span class="p">:</span> <span class="nb">str</span>
|
||||
<span class="n">lens_model</span><span class="p">:</span> <span class="nb">str</span></div>
|
||||
</pre></div>
|
||||
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<footer>
|
||||
|
||||
<div class="related-pages">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../../index.html">osxphotos</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../overview.html">osxphotos</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../tutorial.html">Tutorial</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">osxphotos command line interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">osxphotos package</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../../index.html">Documentation overview</a><ul>
|
||||
<li><a href="../index.html">Module code</a><ul>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="bottom-of-page">
|
||||
<div class="left-details">
|
||||
<div class="copyright">
|
||||
Copyright © 2021, Rhet Turnbull
|
||||
</div>
|
||||
Made with <a href="https://www.sphinx-doc.org/">Sphinx</a> and <a class="muted-link" href="https://pradyunsg.me">@pradyunsg</a>'s
|
||||
|
||||
<a href="https://github.com/pradyunsg/furo">Furo</a>
|
||||
|
||||
</div>
|
||||
<div class="right-details">
|
||||
<div class="icons">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
|
||||
</footer>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2021, Rhet Turnbull.
|
||||
<aside class="toc-drawer no-toc">
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
|
||||
<script src="../../_static/jquery.js"></script>
|
||||
<script src="../../_static/underscore.js"></script>
|
||||
<script src="../../_static/_sphinx_javascript_frameworks_compat.js"></script>
|
||||
<script src="../../_static/doctools.js"></script>
|
||||
<script src="../../_static/sphinx_highlight.js"></script>
|
||||
<script src="../../_static/scripts/furo.js"></script>
|
||||
<script src="../../_static/clipboard.min.js"></script>
|
||||
<script src="../../_static/copybutton.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.exiftool - osxphotos 0.55.6 documentation</title>
|
||||
<title>osxphotos.exiftool - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.55.6 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.55.6 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.fileutil - osxphotos 0.54.2 documentation</title>
|
||||
<title>osxphotos.fileutil - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.54.2 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.2 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -206,9 +206,12 @@
|
||||
<span class="kn">from</span> <span class="nn">abc</span> <span class="kn">import</span> <span class="n">ABC</span><span class="p">,</span> <span class="n">abstractmethod</span>
|
||||
<span class="kn">from</span> <span class="nn">tempfile</span> <span class="kn">import</span> <span class="n">TemporaryDirectory</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">Foundation</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">.imageconverter</span> <span class="kn">import</span> <span class="n">ImageConverter</span>
|
||||
<span class="kn">from</span> <span class="nn">.platform</span> <span class="kn">import</span> <span class="n">is_macos</span>
|
||||
<span class="kn">from</span> <span class="nn">.unicode</span> <span class="kn">import</span> <span class="n">normalize_fs_path</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">is_macos</span><span class="p">:</span>
|
||||
<span class="kn">import</span> <span class="nn">Foundation</span>
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"FileUtilABC"</span><span class="p">,</span> <span class="s2">"FileUtilMacOS"</span><span class="p">,</span> <span class="s2">"FileUtilShUtil"</span><span class="p">,</span> <span class="s2">"FileUtil"</span><span class="p">,</span> <span class="s2">"FileUtilNoOp"</span><span class="p">]</span>
|
||||
|
||||
@@ -287,6 +290,9 @@
|
||||
<span class="k">if</span> <span class="n">src</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">dest</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"src and dest must not be None"</span><span class="p">,</span> <span class="n">src</span><span class="p">,</span> <span class="n">dest</span><span class="p">)</span>
|
||||
|
||||
<span class="n">src</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">src</span><span class="p">)</span>
|
||||
<span class="n">dest</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isfile</span><span class="p">(</span><span class="n">src</span><span class="p">):</span>
|
||||
<span class="k">raise</span> <span class="ne">FileNotFoundError</span><span class="p">(</span><span class="s2">"src file does not appear to exist"</span><span class="p">,</span> <span class="n">src</span><span class="p">)</span>
|
||||
|
||||
@@ -312,6 +318,9 @@
|
||||
<span class="sd"> OSError if copy fails</span>
|
||||
<span class="sd"> TypeError if either path is None</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">src</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">src</span><span class="p">)</span>
|
||||
<span class="n">dest</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">):</span>
|
||||
<span class="n">src</span> <span class="o">=</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="n">src</span><span class="p">)</span>
|
||||
|
||||
@@ -332,6 +341,7 @@
|
||||
<span class="nd">@classmethod</span>
|
||||
<span class="k">def</span> <span class="nf">unlink</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">filepath</span><span class="p">):</span>
|
||||
<span class="sd">"""unlink filepath; if it's pathlib.Path, use Path.unlink, otherwise use os.unlink"""</span>
|
||||
<span class="n">filepath</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">filepath</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">filepath</span><span class="p">,</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">):</span>
|
||||
<span class="n">filepath</span><span class="o">.</span><span class="n">unlink</span><span class="p">()</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
@@ -340,6 +350,7 @@
|
||||
<span class="nd">@classmethod</span>
|
||||
<span class="k">def</span> <span class="nf">rmdir</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">dirpath</span><span class="p">):</span>
|
||||
<span class="sd">"""remove directory filepath; dirpath must be empty"""</span>
|
||||
<span class="n">dirpath</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">dirpath</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">dirpath</span><span class="p">,</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">):</span>
|
||||
<span class="n">dirpath</span><span class="o">.</span><span class="n">rmdir</span><span class="p">()</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
@@ -348,6 +359,7 @@
|
||||
<span class="nd">@classmethod</span>
|
||||
<span class="k">def</span> <span class="nf">utime</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">times</span><span class="p">):</span>
|
||||
<span class="sd">"""Set the access and modified time of path."""</span>
|
||||
<span class="n">path</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
|
||||
<span class="n">os</span><span class="o">.</span><span class="n">utime</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">times</span><span class="o">=</span><span class="n">times</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@classmethod</span>
|
||||
@@ -363,6 +375,9 @@
|
||||
<span class="sd"> Does not do a byte-by-byte comparison.</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="n">f1</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">f1</span><span class="p">)</span>
|
||||
<span class="n">f2</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">f2</span><span class="p">)</span>
|
||||
|
||||
<span class="n">s1</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_sig</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">f1</span><span class="p">))</span>
|
||||
<span class="k">if</span> <span class="n">mtime1</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="n">s1</span> <span class="o">=</span> <span class="p">(</span><span class="n">s1</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">s1</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nb">int</span><span class="p">(</span><span class="n">mtime1</span><span class="p">))</span>
|
||||
@@ -385,6 +400,7 @@
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">s2</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="kc">False</span>
|
||||
|
||||
<span class="n">f1</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">f1</span><span class="p">)</span>
|
||||
<span class="n">s1</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_sig</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">f1</span><span class="p">))</span>
|
||||
<span class="k">if</span> <span class="n">s1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="n">stat</span><span class="o">.</span><span class="n">S_IFREG</span> <span class="ow">or</span> <span class="n">s2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="n">stat</span><span class="o">.</span><span class="n">S_IFREG</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="kc">False</span>
|
||||
@@ -393,6 +409,7 @@
|
||||
<span class="nd">@classmethod</span>
|
||||
<span class="k">def</span> <span class="nf">file_sig</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">f1</span><span class="p">):</span>
|
||||
<span class="sd">"""return os.stat signature for file f1 as tuple of (mode, size, mtime)"""</span>
|
||||
<span class="n">f1</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">f1</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_sig</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">f1</span><span class="p">))</span>
|
||||
|
||||
<span class="nd">@classmethod</span>
|
||||
@@ -407,6 +424,8 @@
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> True if success, otherwise False</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">src_file</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">src_file</span><span class="p">)</span>
|
||||
<span class="n">dest_file</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">dest_file</span><span class="p">)</span>
|
||||
<span class="n">converter</span> <span class="o">=</span> <span class="n">ImageConverter</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="n">converter</span><span class="o">.</span><span class="n">write_jpeg</span><span class="p">(</span>
|
||||
<span class="n">src_file</span><span class="p">,</span> <span class="n">dest_file</span><span class="p">,</span> <span class="n">compression_quality</span><span class="o">=</span><span class="n">compression_quality</span>
|
||||
@@ -424,6 +443,8 @@
|
||||
<span class="sd"> Name of renamed file (dest)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">src</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">src</span><span class="p">)</span>
|
||||
<span class="n">dest</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
|
||||
<span class="n">os</span><span class="o">.</span><span class="n">rename</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">src</span><span class="p">),</span> <span class="nb">str</span><span class="p">(</span><span class="n">dest</span><span class="p">))</span>
|
||||
<span class="k">return</span> <span class="n">dest</span>
|
||||
|
||||
@@ -468,6 +489,9 @@
|
||||
<span class="sd"> OSError if copy fails</span>
|
||||
<span class="sd"> TypeError if either path is None</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">src</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">src</span><span class="p">)</span>
|
||||
<span class="n">dest</span> <span class="o">=</span> <span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">):</span>
|
||||
<span class="n">src</span> <span class="o">=</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="n">src</span><span class="p">)</span>
|
||||
|
||||
@@ -485,7 +509,7 @@
|
||||
<span class="k">return</span> <span class="kc">True</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="FileUtil"><a class="viewcode-back" href="../../reference.html#osxphotos.FileUtil">[docs]</a><span class="k">class</span> <span class="nc">FileUtil</span><span class="p">(</span><span class="n">FileUtilMacOS</span><span class="p">):</span>
|
||||
<div class="viewcode-block" id="FileUtil"><a class="viewcode-back" href="../../reference.html#osxphotos.FileUtil">[docs]</a><span class="k">class</span> <span class="nc">FileUtil</span><span class="p">(</span><span class="n">FileUtilShUtil</span><span class="p">):</span>
|
||||
<span class="sd">"""Various file utilities"""</span>
|
||||
|
||||
<span class="k">pass</span></div>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!doctype html>
|
||||
<html class="no-js">
|
||||
<html class="no-js" lang="en">
|
||||
<head><meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
|
||||
<title>osxphotos.momentinfo - osxphotos 0.48.3 documentation</title>
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.momentinfo - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=68f4518137b9aefe99b631505a2064c3c42c9852" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.48.3 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.48.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -179,7 +179,8 @@
|
||||
</svg>
|
||||
<span>Back to top</span>
|
||||
</a>
|
||||
<div class="content-icon-container"><div class="theme-toggle-container theme-toggle-content">
|
||||
<div class="content-icon-container">
|
||||
<div class="theme-toggle-container theme-toggle-content">
|
||||
<button class="theme-toggle">
|
||||
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
|
||||
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||||
@@ -194,91 +195,91 @@
|
||||
</div>
|
||||
<article role="main">
|
||||
<h1>Source code for osxphotos.momentinfo</h1><div class="highlight"><pre>
|
||||
<span></span><span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"MomentInfo"</span><span class="p">]</span>
|
||||
<span class="sd">"""MomentInfo class with details about photo moments."""</span>
|
||||
<span></span><span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"MomentInfo"</span><span class="p">]</span>
|
||||
<span class="sd">"""MomentInfo class with details about photo moments."""</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="MomentInfo"><a class="viewcode-back" href="../../reference.html#osxphotos.MomentInfo">[docs]</a><span class="k">class</span> <span class="nc">MomentInfo</span><span class="p">:</span>
|
||||
<span class="sd">"""Info about a photo moment"""</span>
|
||||
<span class="sd">"""Info about a photo moment"""</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">db</span><span class="p">,</span> <span class="n">moment_pk</span><span class="p">):</span>
|
||||
<span class="sd">"""Initialize with a moment PK; returns None if PK not found."""</span>
|
||||
<span class="sd">"""Initialize with a moment PK; returns None if PK not found."""</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_db</span> <span class="o">=</span> <span class="n">db</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_pk</span> <span class="o">=</span> <span class="n">moment_pk</span>
|
||||
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_moment</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_db_moment_pk</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">moment_pk</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"No moment with PK </span><span class="si">{</span><span class="n">moment_pk</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"No moment with PK </span><span class="si">{</span><span class="n">moment_pk</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">pk</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Primary key of the moment."""</span>
|
||||
<span class="sd">"""Primary key of the moment."""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pk</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">location</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Location of the moment."""</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"latitude"</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"longitude"</span><span class="p">))</span>
|
||||
<span class="sd">"""Location of the moment."""</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"latitude"</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"longitude"</span><span class="p">))</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">title</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Title of the moment."""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"title"</span><span class="p">)</span>
|
||||
<span class="sd">"""Title of the moment."""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"title"</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">subtitle</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Subtitle of the moment."""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"subtitle"</span><span class="p">)</span>
|
||||
<span class="sd">"""Subtitle of the moment."""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"subtitle"</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">start_date</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Start date of the moment."""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"startDate"</span><span class="p">)</span>
|
||||
<span class="sd">"""Start date of the moment."""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"startDate"</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">end_date</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Stop date of the moment."""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"endDate"</span><span class="p">)</span>
|
||||
<span class="sd">"""Stop date of the moment."""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"endDate"</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">date</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Date of the moment."""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"representativeDate"</span><span class="p">)</span>
|
||||
<span class="sd">"""Date of the moment."""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"representativeDate"</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">modification_date</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Modification date of the moment."""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"modificationDate"</span><span class="p">)</span>
|
||||
<span class="sd">"""Modification date of the moment."""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_moment</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"modificationDate"</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">photos</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""All photos in this moment"""</span>
|
||||
<span class="sd">"""All photos in this moment"""</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photos</span>
|
||||
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
|
||||
<span class="n">photo_uuids</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="n">uuid</span>
|
||||
<span class="k">for</span> <span class="n">uuid</span><span class="p">,</span> <span class="n">photo</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbphotos</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="n">photo</span><span class="p">[</span><span class="s2">"momentID"</span><span class="p">]</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pk</span>
|
||||
<span class="k">if</span> <span class="n">photo</span><span class="p">[</span><span class="s2">"momentID"</span><span class="p">]</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pk</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_photos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">photos_by_uuid</span><span class="p">(</span><span class="n">photo_uuids</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photos</span>
|
||||
|
||||
<div class="viewcode-block" id="MomentInfo.asdict"><a class="viewcode-back" href="../../reference.html#osxphotos.MomentInfo.asdict">[docs]</a> <span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns all moment info as dictionary"""</span>
|
||||
<span class="sd">"""Returns all moment info as dictionary"""</span>
|
||||
<span class="k">return</span> <span class="p">{</span>
|
||||
<span class="s2">"pk"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">pk</span><span class="p">,</span>
|
||||
<span class="s2">"location"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">location</span><span class="p">,</span>
|
||||
<span class="s2">"title"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">,</span>
|
||||
<span class="s2">"subtitle"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">subtitle</span><span class="p">,</span>
|
||||
<span class="s2">"start_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">start_date</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">start_date</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"end_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">end_date</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">end_date</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">date</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"modification_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">modification_date</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span>
|
||||
<span class="s2">"pk"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">pk</span><span class="p">,</span>
|
||||
<span class="s2">"location"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">location</span><span class="p">,</span>
|
||||
<span class="s2">"title"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">,</span>
|
||||
<span class="s2">"subtitle"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">subtitle</span><span class="p">,</span>
|
||||
<span class="s2">"start_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">start_date</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">start_date</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"end_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">end_date</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">end_date</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">date</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"modification_date"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">modification_date</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">modification_date</span>
|
||||
<span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"photos"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">photos</span><span class="p">,</span>
|
||||
<span class="s2">"photos"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">photos</span><span class="p">,</span>
|
||||
<span class="p">}</span></div></div>
|
||||
</pre></div>
|
||||
</article>
|
||||
@@ -317,7 +318,9 @@
|
||||
</div><script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
|
||||
<script src="../../_static/jquery.js"></script>
|
||||
<script src="../../_static/underscore.js"></script>
|
||||
<script src="../../_static/_sphinx_javascript_frameworks_compat.js"></script>
|
||||
<script src="../../_static/doctools.js"></script>
|
||||
<script src="../../_static/sphinx_highlight.js"></script>
|
||||
<script src="../../_static/scripts/furo.js"></script>
|
||||
<script src="../../_static/clipboard.min.js"></script>
|
||||
<script src="../../_static/copybutton.js"></script>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!doctype html>
|
||||
<html class="no-js">
|
||||
<html class="no-js" lang="en">
|
||||
<head><meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
|
||||
<title>osxphotos.personinfo - osxphotos 0.50.4 documentation</title>
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.personinfo - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=68f4518137b9aefe99b631505a2064c3c42c9852" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.50.4 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.50.4 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -179,7 +179,8 @@
|
||||
</svg>
|
||||
<span>Back to top</span>
|
||||
</a>
|
||||
<div class="content-icon-container"><div class="theme-toggle-container theme-toggle-content">
|
||||
<div class="content-icon-container">
|
||||
<div class="theme-toggle-container theme-toggle-content">
|
||||
<button class="theme-toggle">
|
||||
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
|
||||
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||||
@@ -194,25 +195,27 @@
|
||||
</div>
|
||||
<article role="main">
|
||||
<h1>Source code for osxphotos.personinfo</h1><div class="highlight"><pre>
|
||||
<span></span><span class="sd">""" PhotoInfo and FaceInfo classes to expose info about persons and faces in the Photos library """</span>
|
||||
<span></span><span class="sd">""" PhotoInfo and FaceInfo classes to expose info about persons and faces in the Photos library """</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">json</span>
|
||||
<span class="kn">import</span> <span class="nn">logging</span>
|
||||
<span class="kn">import</span> <span class="nn">math</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>
|
||||
<span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="n">cached_property</span>
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"PersonInfo"</span><span class="p">,</span> <span class="s2">"FaceInfo"</span><span class="p">,</span> <span class="s2">"rotate_image_point"</span><span class="p">]</span>
|
||||
<span class="kn">import</span> <span class="nn">osxphotos</span>
|
||||
|
||||
<span class="n">MWG_RS_Area</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s2">"MWG_RS_Area"</span><span class="p">,</span> <span class="p">[</span><span class="s2">"x"</span><span class="p">,</span> <span class="s2">"y"</span><span class="p">,</span> <span class="s2">"h"</span><span class="p">,</span> <span class="s2">"w"</span><span class="p">])</span>
|
||||
<span class="n">MPRI_Reg_Rect</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s2">"MPRI_Reg_Rect"</span><span class="p">,</span> <span class="p">[</span><span class="s2">"x"</span><span class="p">,</span> <span class="s2">"y"</span><span class="p">,</span> <span class="s2">"h"</span><span class="p">,</span> <span class="s2">"w"</span><span class="p">])</span>
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"PersonInfo"</span><span class="p">,</span> <span class="s2">"FaceInfo"</span><span class="p">,</span> <span class="s2">"rotate_image_point"</span><span class="p">]</span>
|
||||
|
||||
<span class="n">MWG_RS_Area</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s2">"MWG_RS_Area"</span><span class="p">,</span> <span class="p">[</span><span class="s2">"x"</span><span class="p">,</span> <span class="s2">"y"</span><span class="p">,</span> <span class="s2">"h"</span><span class="p">,</span> <span class="s2">"w"</span><span class="p">])</span>
|
||||
<span class="n">MPRI_Reg_Rect</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s2">"MPRI_Reg_Rect"</span><span class="p">,</span> <span class="p">[</span><span class="s2">"x"</span><span class="p">,</span> <span class="s2">"y"</span><span class="p">,</span> <span class="s2">"h"</span><span class="p">,</span> <span class="s2">"w"</span><span class="p">])</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="PersonInfo"><a class="viewcode-back" href="../../reference.html#osxphotos.PersonInfo">[docs]</a><span class="k">class</span> <span class="nc">PersonInfo</span><span class="p">:</span>
|
||||
<span class="sd">"""Info about a person in the Photos library"""</span>
|
||||
<span class="sd">"""Info about a person in the Photos library"""</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">db</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">pk</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||||
<span class="sd">"""Creates a new PersonInfo instance</span>
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">db</span><span class="p">:</span> <span class="s2">"osxphotos.PhotosDB"</span><span class="p">,</span> <span class="n">pk</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span>
|
||||
<span class="sd">"""Creates a new PersonInfo instance</span>
|
||||
|
||||
<span class="sd"> Arguments:</span>
|
||||
<span class="sd"> db: instance of PhotosDB object</span>
|
||||
@@ -220,16 +223,16 @@
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> PersonInfo instance</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_db</span> <span class="o">=</span> <span class="n">db</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_pk</span> <span class="o">=</span> <span class="n">pk</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="p">:</span> <span class="s2">"osxphotos.PhotosDB"</span> <span class="o">=</span> <span class="n">db</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_pk</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="n">pk</span>
|
||||
|
||||
<span class="n">person</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbpersons_pk</span><span class="p">[</span><span class="n">pk</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">uuid</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"uuid"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"fullname"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">display_name</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"displayname"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">keyface</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"keyface"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">facecount</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"facecount"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">uuid</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"uuid"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"fullname"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">display_name</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"displayname"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">keyface</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"keyface"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">facecount</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="s2">"facecount"</span><span class="p">]</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">keyphoto</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
@@ -237,9 +240,9 @@
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_keyphoto</span>
|
||||
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
|
||||
<span class="n">person</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbpersons_pk</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_pk</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="n">person</span><span class="p">[</span><span class="s2">"photo_uuid"</span><span class="p">]:</span>
|
||||
<span class="k">if</span> <span class="n">person</span><span class="p">[</span><span class="s2">"photo_uuid"</span><span class="p">]:</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">key_photo</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">get_photo</span><span class="p">(</span><span class="n">person</span><span class="p">[</span><span class="s2">"photo_uuid"</span><span class="p">])</span>
|
||||
<span class="n">key_photo</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">get_photo</span><span class="p">(</span><span class="n">person</span><span class="p">[</span><span class="s2">"photo_uuid"</span><span class="p">])</span>
|
||||
<span class="k">except</span> <span class="ne">IndexError</span><span class="p">:</span>
|
||||
<span class="n">key_photo</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
@@ -249,14 +252,14 @@
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">photos</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns list of PhotoInfo objects associated with this person"""</span>
|
||||
<span class="sd">"""Returns list of PhotoInfo objects associated with this person"""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">photos_by_uuid</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbfaces_pk</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_pk</span><span class="p">])</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">face_info</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns a list of FaceInfo objects associated with this person sorted by quality score</span>
|
||||
<span class="sd">"""Returns a list of FaceInfo objects associated with this person sorted by quality score</span>
|
||||
<span class="sd"> Highest quality face is result[0] and lowest quality face is result[n]</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">faces</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_db_faceinfo_person</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_pk</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="nb">sorted</span><span class="p">(</span>
|
||||
@@ -268,30 +271,60 @@
|
||||
<span class="c1"># no faces</span>
|
||||
<span class="k">return</span> <span class="p">[]</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">favorite</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns True if person is a favorite, False otherwise; Photos 5+ only; returns False on Photos <= 4"""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbpersons_pk</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_pk</span><span class="p">][</span><span class="s2">"type"</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">sort_order</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns sort order of person; favorite persons are sorted before non-favorite persons"; Photos 5+ only; returns 0 on Photos <= 4"""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_dbpersons_pk</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_pk</span><span class="p">][</span><span class="s2">"manualorder"</span><span class="p">]</span>
|
||||
|
||||
<span class="nd">@cached_property</span>
|
||||
<span class="k">def</span> <span class="nf">feature_less</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns True if person has been marked as "Feature This Person Less" in Photos, False otherwise; Photos 8+ only; returns False on Photos <= 7"""</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">photos_version</span> <span class="o"><</span> <span class="mi">8</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="kc">False</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">results</span> <span class="o">:=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> SELECT ZTYPE</span>
|
||||
<span class="sd"> FROM ZUSERFEEDBACK</span>
|
||||
<span class="sd"> WHERE ZPERSON = ?</span>
|
||||
<span class="sd"> """</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_pk</span><span class="p">,),</span>
|
||||
<span class="p">)</span><span class="o">.</span><span class="n">fetchone</span><span class="p">():</span>
|
||||
<span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="n">results</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||||
<span class="k">return</span> <span class="kc">False</span>
|
||||
|
||||
<div class="viewcode-block" id="PersonInfo.asdict"><a class="viewcode-back" href="../../reference.html#osxphotos.PersonInfo.asdict">[docs]</a> <span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns dictionary representation of class instance"""</span>
|
||||
<span class="sd">"""Returns dictionary representation of class instance"""</span>
|
||||
<span class="n">keyphoto</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">keyphoto</span><span class="o">.</span><span class="n">uuid</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">keyphoto</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="kc">None</span>
|
||||
<span class="k">return</span> <span class="p">{</span>
|
||||
<span class="s2">"uuid"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="p">,</span>
|
||||
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||||
<span class="s2">"displayname"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">display_name</span><span class="p">,</span>
|
||||
<span class="s2">"keyface"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">keyface</span><span class="p">,</span>
|
||||
<span class="s2">"facecount"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">facecount</span><span class="p">,</span>
|
||||
<span class="s2">"keyphoto"</span><span class="p">:</span> <span class="n">keyphoto</span><span class="p">,</span>
|
||||
<span class="s2">"uuid"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="p">,</span>
|
||||
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||||
<span class="s2">"displayname"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">display_name</span><span class="p">,</span>
|
||||
<span class="s2">"keyface"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">keyface</span><span class="p">,</span>
|
||||
<span class="s2">"facecount"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">facecount</span><span class="p">,</span>
|
||||
<span class="s2">"keyphoto"</span><span class="p">:</span> <span class="n">keyphoto</span><span class="p">,</span>
|
||||
<span class="s2">"favorite"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">favorite</span><span class="p">,</span>
|
||||
<span class="s2">"sort_order"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">sort_order</span><span class="p">,</span>
|
||||
<span class="s2">"feature_less"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">feature_less</span><span class="p">,</span>
|
||||
<span class="p">}</span></div>
|
||||
|
||||
<div class="viewcode-block" id="PersonInfo.json"><a class="viewcode-back" href="../../reference.html#osxphotos.PersonInfo.json">[docs]</a> <span class="k">def</span> <span class="nf">json</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns JSON representation of class instance"""</span>
|
||||
<span class="sd">"""Returns JSON representation of class instance"""</span>
|
||||
<span class="k">return</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">asdict</span><span class="p">())</span></div>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"PersonInfo(name=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">, display_name=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">display_name</span><span class="si">}</span><span class="s2">, uuid=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="si">}</span><span class="s2">, facecount=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">facecount</span><span class="si">}</span><span class="s2">)"</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"PersonInfo(name=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">, display_name=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">display_name</span><span class="si">}</span><span class="s2">, uuid=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="si">}</span><span class="s2">, facecount=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">facecount</span><span class="si">}</span><span class="s2">)"</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="p">(</span>
|
||||
<span class="nb">all</span><span class="p">(</span>
|
||||
<span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="o">==</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"_db"</span><span class="p">,</span> <span class="s2">"_pk"</span><span class="p">]</span>
|
||||
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"_db"</span><span class="p">,</span> <span class="s2">"_pk"</span><span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>
|
||||
<span class="k">else</span> <span class="kc">False</span>
|
||||
@@ -301,11 +334,11 @@
|
||||
<span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__eq__</span><span class="p">(</span><span class="n">other</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<span class="k">class</span> <span class="nc">FaceInfo</span><span class="p">:</span>
|
||||
<span class="sd">"""Info about a face in the Photos library"""</span>
|
||||
<div class="viewcode-block" id="FaceInfo"><a class="viewcode-back" href="../../reference.html#osxphotos.FaceInfo">[docs]</a><span class="k">class</span> <span class="nc">FaceInfo</span><span class="p">:</span>
|
||||
<span class="sd">"""Info about a face in the Photos library"""</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">db</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">pk</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||||
<span class="sd">"""Creates a new FaceInfo instance</span>
|
||||
<span class="sd">"""Creates a new FaceInfo instance</span>
|
||||
|
||||
<span class="sd"> Arguments:</span>
|
||||
<span class="sd"> db: instance of PhotosDB object</span>
|
||||
@@ -313,59 +346,59 @@
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> FaceInfo instance</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_db</span> <span class="o">=</span> <span class="n">db</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_pk</span> <span class="o">=</span> <span class="n">pk</span>
|
||||
|
||||
<span class="n">face</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_db_faceinfo_pk</span><span class="p">[</span><span class="n">pk</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_info</span> <span class="o">=</span> <span class="n">face</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">uuid</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"uuid"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"fullname"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"asset_uuid"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_person_pk</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"person"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">center_x</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"centerx"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">center_y</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"centery"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"size"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">quality</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"quality"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">source_width</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"sourcewidth"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">source_height</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"sourceheight"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">has_smile</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"has_smile"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">manual</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"manual"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">face_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"facetype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">age_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"agetype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">eye_makeup_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"eyemakeuptype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">eye_state</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"eyestate"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">facial_hair_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"facialhairtype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">gender_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"gendertype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">glasses_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"glassestype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">hair_color_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"haircolortype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">intrash</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"intrash"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">lip_makeup_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"lipmakeuptype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">smile_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"smiletype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">uuid</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"uuid"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"fullname"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"asset_uuid"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_person_pk</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"person"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">center_x</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"centerx"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">center_y</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"centery"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"size"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">quality</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"quality"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">source_width</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"sourcewidth"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">source_height</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"sourceheight"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">has_smile</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"has_smile"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">manual</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"manual"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">face_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"facetype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">age_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"agetype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">eye_makeup_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"eyemakeuptype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">eye_state</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"eyestate"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">facial_hair_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"facialhairtype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">gender_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"gendertype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">glasses_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"glassestype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">hair_color_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"haircolortype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">intrash</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"intrash"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">lip_makeup_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"lipmakeuptype"</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">smile_type</span> <span class="o">=</span> <span class="n">face</span><span class="p">[</span><span class="s2">"smiletype"</span><span class="p">]</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">center</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Coordinates, in PIL format, for center of face</span>
|
||||
<span class="sd">"""Coordinates, in PIL format, for center of face</span>
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> tuple of coordinates in form (x, y)</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_make_point</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_y</span><span class="p">))</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">size_pixels</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Size of face in pixels (centered around center_x, center_y)</span>
|
||||
<span class="sd">"""Size of face in pixels (centered around center_x, center_y)</span>
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> size, in int pixels, of a circle drawn around the center of the face</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">photo</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span>
|
||||
<span class="n">size_reference</span> <span class="o">=</span> <span class="n">photo</span><span class="o">.</span><span class="n">width</span> <span class="k">if</span> <span class="n">photo</span><span class="o">.</span><span class="n">width</span> <span class="o">></span> <span class="n">photo</span><span class="o">.</span><span class="n">height</span> <span class="k">else</span> <span class="n">photo</span><span class="o">.</span><span class="n">height</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">*</span> <span class="n">size_reference</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">person_info</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""PersonInfo instance for person associated with this face"""</span>
|
||||
<span class="sd">"""PersonInfo instance for person associated with this face"""</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_person</span>
|
||||
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
|
||||
@@ -374,18 +407,18 @@
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">photo</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""PhotoInfo instance associated with this face"""</span>
|
||||
<span class="sd">"""PhotoInfo instance associated with this face"""</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photo</span>
|
||||
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_photo</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">get_photo</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photo</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Could not get photo for uuid: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Could not get photo for uuid: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photo</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">mwg_rs_area</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Get coordinates for Metadata Working Group Region Area.</span>
|
||||
<span class="sd">"""Get coordinates for Metadata Working Group Region Area.</span>
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> MWG_RS_Area named tuple with x, y, h, w where:</span>
|
||||
@@ -396,7 +429,7 @@
|
||||
|
||||
<span class="sd"> Reference:</span>
|
||||
<span class="sd"> https://photo.stackexchange.com/questions/106410/how-does-xmp-define-the-face-region</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_y</span>
|
||||
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fix_orientation</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
|
||||
|
||||
@@ -411,7 +444,7 @@
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">mpri_reg_rect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Get coordinates for Microsoft Photo Region Rectangle.</span>
|
||||
<span class="sd">"""Get coordinates for Microsoft Photo Region Rectangle.</span>
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> MPRI_Reg_Rect named tuple with x, y, h, w where:</span>
|
||||
@@ -422,7 +455,7 @@
|
||||
|
||||
<span class="sd"> Reference:</span>
|
||||
<span class="sd"> https://docs.microsoft.com/en-us/windows/win32/wic/-wic-people-tagging</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_y</span>
|
||||
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fix_orientation</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
|
||||
|
||||
@@ -439,51 +472,51 @@
|
||||
|
||||
<span class="k">return</span> <span class="n">MPRI_Reg_Rect</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">h</span><span class="p">,</span> <span class="n">w</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">face_rect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Get face rectangle coordinates for current version of the associated image</span>
|
||||
<div class="viewcode-block" id="FaceInfo.face_rect"><a class="viewcode-back" href="../../reference.html#osxphotos.FaceInfo.face_rect">[docs]</a> <span class="k">def</span> <span class="nf">face_rect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Get face rectangle coordinates for current version of the associated image</span>
|
||||
<span class="sd"> If image has been edited, rectangle applies to edited version, otherwise original version</span>
|
||||
<span class="sd"> Coordinates in format and reference frame used by PIL</span>
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> list [(x0, x1), (y0, y1)] of coordinates in reference frame used by PIL</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">photo</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span>
|
||||
<span class="n">size_reference</span> <span class="o">=</span> <span class="n">photo</span><span class="o">.</span><span class="n">width</span> <span class="k">if</span> <span class="n">photo</span><span class="o">.</span><span class="n">width</span> <span class="o">></span> <span class="n">photo</span><span class="o">.</span><span class="n">height</span> <span class="k">else</span> <span class="n">photo</span><span class="o">.</span><span class="n">height</span>
|
||||
<span class="n">radius</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span> <span class="o">*</span> <span class="n">size_reference</span>
|
||||
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_make_point</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_y</span><span class="p">))</span>
|
||||
<span class="n">x0</span><span class="p">,</span> <span class="n">y0</span> <span class="o">=</span> <span class="n">x</span> <span class="o">-</span> <span class="n">radius</span><span class="p">,</span> <span class="n">y</span> <span class="o">-</span> <span class="n">radius</span>
|
||||
<span class="n">x1</span><span class="p">,</span> <span class="n">y1</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">radius</span><span class="p">,</span> <span class="n">y</span> <span class="o">+</span> <span class="n">radius</span>
|
||||
<span class="k">return</span> <span class="p">[(</span><span class="n">x0</span><span class="p">,</span> <span class="n">y0</span><span class="p">),</span> <span class="p">(</span><span class="n">x1</span><span class="p">,</span> <span class="n">y1</span><span class="p">)]</span>
|
||||
<span class="k">return</span> <span class="p">[(</span><span class="n">x0</span><span class="p">,</span> <span class="n">y0</span><span class="p">),</span> <span class="p">(</span><span class="n">x1</span><span class="p">,</span> <span class="n">y1</span><span class="p">)]</span></div>
|
||||
|
||||
<span class="k">def</span> <span class="nf">roll_pitch_yaw</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Roll, pitch, yaw of face in radians as tuple"""</span>
|
||||
<div class="viewcode-block" id="FaceInfo.roll_pitch_yaw"><a class="viewcode-back" href="../../reference.html#osxphotos.FaceInfo.roll_pitch_yaw">[docs]</a> <span class="k">def</span> <span class="nf">roll_pitch_yaw</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Roll, pitch, yaw of face in radians as tuple"""</span>
|
||||
<span class="n">info</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_info</span>
|
||||
<span class="n">roll</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">info</span><span class="p">[</span><span class="s2">"roll"</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">info</span><span class="p">[</span><span class="s2">"roll"</span><span class="p">]</span>
|
||||
<span class="n">pitch</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">info</span><span class="p">[</span><span class="s2">"pitch"</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">info</span><span class="p">[</span><span class="s2">"pitch"</span><span class="p">]</span>
|
||||
<span class="n">yaw</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">info</span><span class="p">[</span><span class="s2">"yaw"</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">info</span><span class="p">[</span><span class="s2">"yaw"</span><span class="p">]</span>
|
||||
<span class="n">roll</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">info</span><span class="p">[</span><span class="s2">"roll"</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">info</span><span class="p">[</span><span class="s2">"roll"</span><span class="p">]</span>
|
||||
<span class="n">pitch</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">info</span><span class="p">[</span><span class="s2">"pitch"</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">info</span><span class="p">[</span><span class="s2">"pitch"</span><span class="p">]</span>
|
||||
<span class="n">yaw</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">if</span> <span class="n">info</span><span class="p">[</span><span class="s2">"yaw"</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">info</span><span class="p">[</span><span class="s2">"yaw"</span><span class="p">]</span>
|
||||
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">roll</span><span class="p">,</span> <span class="n">pitch</span><span class="p">,</span> <span class="n">yaw</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">roll</span><span class="p">,</span> <span class="n">pitch</span><span class="p">,</span> <span class="n">yaw</span><span class="p">)</span></div>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">roll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return roll angle in radians of the face region"""</span>
|
||||
<span class="sd">"""Return roll angle in radians of the face region"""</span>
|
||||
<span class="n">roll</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">roll_pitch_yaw</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="n">roll</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">pitch</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return pitch angle in radians of the face region"""</span>
|
||||
<span class="sd">"""Return pitch angle in radians of the face region"""</span>
|
||||
<span class="n">_</span><span class="p">,</span> <span class="n">pitch</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">roll_pitch_yaw</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="n">pitch</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">yaw</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return yaw angle in radians of the face region"""</span>
|
||||
<span class="sd">"""Return yaw angle in radians of the face region"""</span>
|
||||
<span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">yaw</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">roll_pitch_yaw</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="n">yaw</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_fix_orientation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">xy</span><span class="p">):</span>
|
||||
<span class="sd">"""Translate an (x, y) tuple based on image orientation</span>
|
||||
<span class="sd">"""Translate an (x, y) tuple based on image orientation</span>
|
||||
|
||||
<span class="sd"> Arguments:</span>
|
||||
<span class="sd"> xy: tuple of (x, y) coordinates for point to translate</span>
|
||||
@@ -491,7 +524,7 @@
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> (x, y) tuple of translated coordinates</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="c1"># Reference: https://github.com/neilpa/phace/blob/7594776480505d0c389688a42099c94ac5d34f3f/cmd/phace/draw.go#L79-L94</span>
|
||||
|
||||
<span class="n">orientation</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">orientation</span>
|
||||
@@ -515,15 +548,15 @@
|
||||
<span class="k">elif</span> <span class="n">orientation</span> <span class="o">==</span> <span class="mi">8</span><span class="p">:</span>
|
||||
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">y</span><span class="p">,</span> <span class="n">x</span>
|
||||
<span class="k">elif</span> <span class="n">orientation</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
|
||||
<span class="c1"># set by osxphotos if adjusted orientation cannot be read, assume it's 1</span>
|
||||
<span class="c1"># set by osxphotos if adjusted orientation cannot be read, assume it's 1</span>
|
||||
<span class="n">y</span> <span class="o">=</span> <span class="mf">1.0</span> <span class="o">-</span> <span class="n">y</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unhandled orientation: </span><span class="si">{</span><span class="n">orientation</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unhandled orientation: </span><span class="si">{</span><span class="n">orientation</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_make_point</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">xy</span><span class="p">):</span>
|
||||
<span class="sd">"""Translate an (x, y) tuple based on image orientation</span>
|
||||
<span class="sd">"""Translate an (x, y) tuple based on image orientation</span>
|
||||
<span class="sd"> and convert to image coordinates</span>
|
||||
|
||||
<span class="sd"> Arguments:</span>
|
||||
@@ -532,7 +565,7 @@
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> (x, y) tuple of translated coordinates in pixels in PIL format/reference frame</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="c1"># Reference: https://github.com/neilpa/phace/blob/7594776480505d0c389688a42099c94ac5d34f3f/cmd/phace/draw.go#L79-L94</span>
|
||||
|
||||
<span class="n">orientation</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">orientation</span>
|
||||
@@ -544,7 +577,7 @@
|
||||
<span class="k">return</span> <span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">x</span> <span class="o">*</span> <span class="n">dx</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">y</span> <span class="o">*</span> <span class="n">dy</span><span class="p">))</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_make_point_with_rotation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">xy</span><span class="p">):</span>
|
||||
<span class="sd">"""Translate an (x, y) tuple based on image orientation and rotation</span>
|
||||
<span class="sd">"""Translate an (x, y) tuple based on image orientation and rotation</span>
|
||||
<span class="sd"> and convert to image coordinates</span>
|
||||
|
||||
<span class="sd"> Arguments:</span>
|
||||
@@ -553,7 +586,7 @@
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> (x, y) tuple of translated coordinates in pixels in PIL format/reference frame</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="c1"># convert to image coordinates</span>
|
||||
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_make_point</span><span class="p">(</span><span class="n">xy</span><span class="p">)</span>
|
||||
@@ -565,67 +598,67 @@
|
||||
|
||||
<span class="k">return</span> <span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">xr</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">yr</span><span class="p">))</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns dict representation of class instance"""</span>
|
||||
<div class="viewcode-block" id="FaceInfo.asdict"><a class="viewcode-back" href="../../reference.html#osxphotos.FaceInfo.asdict">[docs]</a> <span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns dict representation of class instance"""</span>
|
||||
<span class="n">roll</span><span class="p">,</span> <span class="n">pitch</span><span class="p">,</span> <span class="n">yaw</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">roll_pitch_yaw</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="p">{</span>
|
||||
<span class="s2">"_pk"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pk</span><span class="p">,</span>
|
||||
<span class="s2">"uuid"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="p">,</span>
|
||||
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||||
<span class="s2">"asset_uuid"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span><span class="p">,</span>
|
||||
<span class="s2">"_person_pk"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_person_pk</span><span class="p">,</span>
|
||||
<span class="s2">"center_x"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="p">,</span>
|
||||
<span class="s2">"center_y"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_y</span><span class="p">,</span>
|
||||
<span class="s2">"center"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">center</span><span class="p">,</span>
|
||||
<span class="s2">"size"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">,</span>
|
||||
<span class="s2">"face_rect"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">face_rect</span><span class="p">(),</span>
|
||||
<span class="s2">"mpri_reg_rect"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">mpri_reg_rect</span><span class="o">.</span><span class="n">_asdict</span><span class="p">(),</span>
|
||||
<span class="s2">"mwg_rs_area"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">mwg_rs_area</span><span class="o">.</span><span class="n">_asdict</span><span class="p">(),</span>
|
||||
<span class="s2">"roll"</span><span class="p">:</span> <span class="n">roll</span><span class="p">,</span>
|
||||
<span class="s2">"pitch"</span><span class="p">:</span> <span class="n">pitch</span><span class="p">,</span>
|
||||
<span class="s2">"yaw"</span><span class="p">:</span> <span class="n">yaw</span><span class="p">,</span>
|
||||
<span class="s2">"quality"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">quality</span><span class="p">,</span>
|
||||
<span class="s2">"source_width"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">source_width</span><span class="p">,</span>
|
||||
<span class="s2">"source_height"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">source_height</span><span class="p">,</span>
|
||||
<span class="s2">"has_smile"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">has_smile</span><span class="p">,</span>
|
||||
<span class="s2">"manual"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">manual</span><span class="p">,</span>
|
||||
<span class="s2">"face_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">face_type</span><span class="p">,</span>
|
||||
<span class="s2">"age_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">age_type</span><span class="p">,</span>
|
||||
<span class="s2">"eye_makeup_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">eye_makeup_type</span><span class="p">,</span>
|
||||
<span class="s2">"eye_state"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">eye_state</span><span class="p">,</span>
|
||||
<span class="s2">"facial_hair_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">facial_hair_type</span><span class="p">,</span>
|
||||
<span class="s2">"gender_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">gender_type</span><span class="p">,</span>
|
||||
<span class="s2">"glasses_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">glasses_type</span><span class="p">,</span>
|
||||
<span class="s2">"hair_color_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">hair_color_type</span><span class="p">,</span>
|
||||
<span class="s2">"intrash"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">intrash</span><span class="p">,</span>
|
||||
<span class="s2">"lip_makeup_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">lip_makeup_type</span><span class="p">,</span>
|
||||
<span class="s2">"smile_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">smile_type</span><span class="p">,</span>
|
||||
<span class="p">}</span>
|
||||
<span class="s2">"_pk"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pk</span><span class="p">,</span>
|
||||
<span class="s2">"uuid"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="p">,</span>
|
||||
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||||
<span class="s2">"asset_uuid"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span><span class="p">,</span>
|
||||
<span class="s2">"_person_pk"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_person_pk</span><span class="p">,</span>
|
||||
<span class="s2">"center_x"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="p">,</span>
|
||||
<span class="s2">"center_y"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_y</span><span class="p">,</span>
|
||||
<span class="s2">"center"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">center</span><span class="p">,</span>
|
||||
<span class="s2">"size"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">,</span>
|
||||
<span class="s2">"face_rect"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">face_rect</span><span class="p">(),</span>
|
||||
<span class="s2">"mpri_reg_rect"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">mpri_reg_rect</span><span class="o">.</span><span class="n">_asdict</span><span class="p">(),</span>
|
||||
<span class="s2">"mwg_rs_area"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">mwg_rs_area</span><span class="o">.</span><span class="n">_asdict</span><span class="p">(),</span>
|
||||
<span class="s2">"roll"</span><span class="p">:</span> <span class="n">roll</span><span class="p">,</span>
|
||||
<span class="s2">"pitch"</span><span class="p">:</span> <span class="n">pitch</span><span class="p">,</span>
|
||||
<span class="s2">"yaw"</span><span class="p">:</span> <span class="n">yaw</span><span class="p">,</span>
|
||||
<span class="s2">"quality"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">quality</span><span class="p">,</span>
|
||||
<span class="s2">"source_width"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">source_width</span><span class="p">,</span>
|
||||
<span class="s2">"source_height"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">source_height</span><span class="p">,</span>
|
||||
<span class="s2">"has_smile"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">has_smile</span><span class="p">,</span>
|
||||
<span class="s2">"manual"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">manual</span><span class="p">,</span>
|
||||
<span class="s2">"face_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">face_type</span><span class="p">,</span>
|
||||
<span class="s2">"age_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">age_type</span><span class="p">,</span>
|
||||
<span class="s2">"eye_makeup_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">eye_makeup_type</span><span class="p">,</span>
|
||||
<span class="s2">"eye_state"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">eye_state</span><span class="p">,</span>
|
||||
<span class="s2">"facial_hair_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">facial_hair_type</span><span class="p">,</span>
|
||||
<span class="s2">"gender_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">gender_type</span><span class="p">,</span>
|
||||
<span class="s2">"glasses_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">glasses_type</span><span class="p">,</span>
|
||||
<span class="s2">"hair_color_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">hair_color_type</span><span class="p">,</span>
|
||||
<span class="s2">"intrash"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">intrash</span><span class="p">,</span>
|
||||
<span class="s2">"lip_makeup_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">lip_makeup_type</span><span class="p">,</span>
|
||||
<span class="s2">"smile_type"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">smile_type</span><span class="p">,</span>
|
||||
<span class="p">}</span></div>
|
||||
|
||||
<span class="k">def</span> <span class="nf">json</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return JSON representation of FaceInfo instance"""</span>
|
||||
<span class="k">return</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">asdict</span><span class="p">())</span>
|
||||
<div class="viewcode-block" id="FaceInfo.json"><a class="viewcode-back" href="../../reference.html#osxphotos.FaceInfo.json">[docs]</a> <span class="k">def</span> <span class="nf">json</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return JSON representation of FaceInfo instance"""</span>
|
||||
<span class="k">return</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">asdict</span><span class="p">())</span></div>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"FaceInfo(uuid=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="si">}</span><span class="s2">, center_x=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="si">}</span><span class="s2">, center_y = </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">center_y</span><span class="si">}</span><span class="s2">, size=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="si">}</span><span class="s2">, person=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">, asset_uuid=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span><span class="si">}</span><span class="s2">)"</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"FaceInfo(uuid=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">uuid</span><span class="si">}</span><span class="s2">, center_x=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">center_x</span><span class="si">}</span><span class="s2">, center_y = </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">center_y</span><span class="si">}</span><span class="s2">, size=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="si">}</span><span class="s2">, person=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">, asset_uuid=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">asset_uuid</span><span class="si">}</span><span class="s2">)"</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"FaceInfo(db=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="si">}</span><span class="s2">, pk=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_pk</span><span class="si">}</span><span class="s2">)"</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"FaceInfo(db=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="si">}</span><span class="s2">, pk=</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_pk</span><span class="si">}</span><span class="s2">)"</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)):</span>
|
||||
<span class="k">return</span> <span class="kc">False</span>
|
||||
|
||||
<span class="k">return</span> <span class="nb">all</span><span class="p">(</span>
|
||||
<span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="o">==</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"_db"</span><span class="p">,</span> <span class="s2">"_pk"</span><span class="p">]</span>
|
||||
<span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="o">==</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"_db"</span><span class="p">,</span> <span class="s2">"_pk"</span><span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__ne__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__eq__</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__eq__</span><span class="p">(</span><span class="n">other</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">rotate_image_point</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">xmid</span><span class="p">,</span> <span class="n">ymid</span><span class="p">,</span> <span class="n">angle</span><span class="p">):</span>
|
||||
<span class="sd">"""rotate image point about xm, ym by angle in radians</span>
|
||||
<span class="sd">"""rotate image point about xm, ym by angle in radians</span>
|
||||
|
||||
<span class="sd"> Arguments:</span>
|
||||
<span class="sd"> x: x coordinate of point to rotate</span>
|
||||
@@ -637,7 +670,7 @@
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> tuple of rotated points (xr, yr)</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="c1"># translate point relative to the mid point</span>
|
||||
<span class="n">x</span> <span class="o">=</span> <span class="n">x</span> <span class="o">-</span> <span class="n">xmid</span>
|
||||
<span class="n">y</span> <span class="o">=</span> <span class="n">y</span> <span class="o">-</span> <span class="n">ymid</span>
|
||||
@@ -688,7 +721,9 @@
|
||||
</div><script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
|
||||
<script src="../../_static/jquery.js"></script>
|
||||
<script src="../../_static/underscore.js"></script>
|
||||
<script src="../../_static/_sphinx_javascript_frameworks_compat.js"></script>
|
||||
<script src="../../_static/doctools.js"></script>
|
||||
<script src="../../_static/sphinx_highlight.js"></script>
|
||||
<script src="../../_static/scripts/furo.js"></script>
|
||||
<script src="../../_static/clipboard.min.js"></script>
|
||||
<script src="../../_static/copybutton.js"></script>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.photoexporter - osxphotos 0.55.6 documentation</title>
|
||||
<title>osxphotos.photoexporter - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.55.6 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.55.6 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -198,6 +198,8 @@
|
||||
<span></span><span class="sd">""" PhotoExport class to export photos</span>
|
||||
<span class="sd">"""</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">annotations</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">dataclasses</span>
|
||||
<span class="kn">import</span> <span class="nn">json</span>
|
||||
<span class="kn">import</span> <span class="nn">logging</span>
|
||||
@@ -205,12 +207,11 @@
|
||||
<span class="kn">import</span> <span class="nn">pathlib</span>
|
||||
<span class="kn">import</span> <span class="nn">re</span>
|
||||
<span class="kn">import</span> <span class="nn">typing</span> <span class="k">as</span> <span class="nn">t</span>
|
||||
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span> <span class="c1"># pylint: disable=syntax-error</span>
|
||||
<span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">asdict</span><span class="p">,</span> <span class="n">dataclass</span>
|
||||
<span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span>
|
||||
<span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">Enum</span>
|
||||
<span class="kn">from</span> <span class="nn">types</span> <span class="kn">import</span> <span class="n">SimpleNamespace</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">photoscript</span>
|
||||
<span class="kn">from</span> <span class="nn">mako.template</span> <span class="kn">import</span> <span class="n">Template</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">._constants</span> <span class="kn">import</span> <span class="p">(</span>
|
||||
@@ -228,18 +229,13 @@
|
||||
<span class="p">)</span>
|
||||
<span class="kn">from</span> <span class="nn">._version</span> <span class="kn">import</span> <span class="n">__version__</span>
|
||||
<span class="kn">from</span> <span class="nn">.datetime_utils</span> <span class="kn">import</span> <span class="n">datetime_tz_to_utc</span>
|
||||
<span class="kn">from</span> <span class="nn">.exiftool</span> <span class="kn">import</span> <span class="n">ExifTool</span><span class="p">,</span> <span class="n">exiftool_can_write</span>
|
||||
<span class="kn">from</span> <span class="nn">.exiftool</span> <span class="kn">import</span> <span class="n">ExifTool</span><span class="p">,</span> <span class="n">ExifToolCaching</span><span class="p">,</span> <span class="n">exiftool_can_write</span><span class="p">,</span> <span class="n">get_exiftool_path</span>
|
||||
<span class="kn">from</span> <span class="nn">.export_db</span> <span class="kn">import</span> <span class="n">ExportDB</span><span class="p">,</span> <span class="n">ExportDBTemp</span>
|
||||
<span class="kn">from</span> <span class="nn">.fileutil</span> <span class="kn">import</span> <span class="n">FileUtil</span>
|
||||
<span class="kn">from</span> <span class="nn">.photokit</span> <span class="kn">import</span> <span class="p">(</span>
|
||||
<span class="n">PHOTOS_VERSION_CURRENT</span><span class="p">,</span>
|
||||
<span class="n">PHOTOS_VERSION_ORIGINAL</span><span class="p">,</span>
|
||||
<span class="n">PHOTOS_VERSION_UNADJUSTED</span><span class="p">,</span>
|
||||
<span class="n">PhotoKitFetchFailed</span><span class="p">,</span>
|
||||
<span class="n">PhotoLibrary</span><span class="p">,</span>
|
||||
<span class="p">)</span>
|
||||
<span class="kn">from</span> <span class="nn">.phototemplate</span> <span class="kn">import</span> <span class="n">RenderOptions</span>
|
||||
<span class="kn">from</span> <span class="nn">.platform</span> <span class="kn">import</span> <span class="n">is_macos</span>
|
||||
<span class="kn">from</span> <span class="nn">.rich_utils</span> <span class="kn">import</span> <span class="n">add_rich_markup_tag</span>
|
||||
<span class="kn">from</span> <span class="nn">.unicode</span> <span class="kn">import</span> <span class="n">normalize_fs_path</span>
|
||||
<span class="kn">from</span> <span class="nn">.uti</span> <span class="kn">import</span> <span class="n">get_preferred_uti_extension</span>
|
||||
<span class="kn">from</span> <span class="nn">.utils</span> <span class="kn">import</span> <span class="p">(</span>
|
||||
<span class="n">hexdigest</span><span class="p">,</span>
|
||||
@@ -247,8 +243,22 @@
|
||||
<span class="n">increment_filename_with_count</span><span class="p">,</span>
|
||||
<span class="n">lineno</span><span class="p">,</span>
|
||||
<span class="n">list_directory</span><span class="p">,</span>
|
||||
<span class="n">lock_filename</span><span class="p">,</span>
|
||||
<span class="n">unlock_filename</span><span class="p">,</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">is_macos</span><span class="p">:</span>
|
||||
<span class="kn">import</span> <span class="nn">photoscript</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">.photokit</span> <span class="kn">import</span> <span class="p">(</span>
|
||||
<span class="n">PHOTOS_VERSION_CURRENT</span><span class="p">,</span>
|
||||
<span class="n">PHOTOS_VERSION_ORIGINAL</span><span class="p">,</span>
|
||||
<span class="n">PHOTOS_VERSION_UNADJUSTED</span><span class="p">,</span>
|
||||
<span class="n">PhotoKitFetchFailed</span><span class="p">,</span>
|
||||
<span class="n">PhotoLibrary</span><span class="p">,</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="s2">"ExportError"</span><span class="p">,</span>
|
||||
<span class="s2">"ExportOptions"</span><span class="p">,</span>
|
||||
@@ -263,6 +273,11 @@
|
||||
<span class="c1"># retry if download_missing/use_photos_export fails the first time (which sometimes it does)</span>
|
||||
<span class="n">MAX_PHOTOSCRIPT_RETRIES</span> <span class="o">=</span> <span class="mi">3</span>
|
||||
|
||||
<span class="c1"># Global to hold the compiled XMP template</span>
|
||||
<span class="c1"># This is expensive to compile so we only want to do it once</span>
|
||||
<span class="n">_global_xmp_template</span><span class="p">:</span> <span class="n">Template</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
|
||||
<span class="c1"># return values for _should_update_photo</span>
|
||||
<span class="k">class</span> <span class="nc">ShouldUpdate</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
||||
<span class="n">NOT_IN_DATABASE</span> <span class="o">=</span> <span class="mi">1</span>
|
||||
@@ -317,6 +332,7 @@
|
||||
<span class="sd"> render_options (RenderOptions): t.Optional osxphotos.phototemplate.RenderOptions instance to specify options for rendering templates</span>
|
||||
<span class="sd"> replace_keywords (bool): if True, keyword_template replaces any keywords, otherwise it's additive</span>
|
||||
<span class="sd"> rich (bool): if True, will use rich markup with verbose output</span>
|
||||
<span class="sd"> export_aae (bool): if True, also exports adjustments as .AAE file</span>
|
||||
<span class="sd"> sidecar_drop_ext (bool, default=False): if True, drops the photo's extension from sidecar filename (e.g. 'IMG_1234.json' instead of 'IMG_1234.JPG.json')</span>
|
||||
<span class="sd"> sidecar: bit field (int): set to one or more of `SIDECAR_XMP`, `SIDECAR_JSON`, `SIDECAR_EXIFTOOL`</span>
|
||||
<span class="sd"> - SIDECAR_JSON: if set will write a json sidecar with data in format readable by exiftool sidecar filename will be dest/filename.json;</span>
|
||||
@@ -369,6 +385,7 @@
|
||||
<span class="n">render_options</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="n">RenderOptions</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">replace_keywords</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
<span class="n">rich</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
<span class="n">export_aae</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
<span class="n">sidecar_drop_ext</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
<span class="n">sidecar</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">0</span>
|
||||
<span class="n">strip</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
@@ -430,6 +447,9 @@
|
||||
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">asdict</span><span class="p">())</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"StagedFiles(</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">asdict</span><span class="p">()</span><span class="si">}</span><span class="s2">)"</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="p">{</span>
|
||||
<span class="s2">"original"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">original</span><span class="p">,</span>
|
||||
@@ -460,12 +480,16 @@
|
||||
<span class="s2">"missing"</span><span class="p">,</span>
|
||||
<span class="s2">"missing_album"</span><span class="p">,</span>
|
||||
<span class="s2">"new"</span><span class="p">,</span>
|
||||
<span class="s2">"aae_written"</span><span class="p">,</span>
|
||||
<span class="s2">"sidecar_exiftool_skipped"</span><span class="p">,</span>
|
||||
<span class="s2">"sidecar_exiftool_written"</span><span class="p">,</span>
|
||||
<span class="s2">"sidecar_json_skipped"</span><span class="p">,</span>
|
||||
<span class="s2">"sidecar_json_written"</span><span class="p">,</span>
|
||||
<span class="s2">"sidecar_xmp_skipped"</span><span class="p">,</span>
|
||||
<span class="s2">"sidecar_xmp_written"</span><span class="p">,</span>
|
||||
<span class="s2">"sidecar_user_written"</span><span class="p">,</span>
|
||||
<span class="s2">"sidecar_user_skipped"</span><span class="p">,</span>
|
||||
<span class="s2">"sidecar_user_error"</span><span class="p">,</span>
|
||||
<span class="s2">"skipped"</span><span class="p">,</span>
|
||||
<span class="s2">"skipped_album"</span><span class="p">,</span>
|
||||
<span class="s2">"to_touch"</span><span class="p">,</span>
|
||||
@@ -490,12 +514,16 @@
|
||||
<span class="n">missing</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">missing_album</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">new</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">aae_written</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_exiftool_skipped</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_exiftool_written</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_json_skipped</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_json_written</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_xmp_skipped</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_xmp_written</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_user_written</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_user_skipped</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_user_error</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">skipped</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">skipped_album</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">to_touch</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
@@ -504,7 +532,6 @@
|
||||
<span class="n">xattr_skipped</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">xattr_written</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="p">):</span>
|
||||
|
||||
<span class="n">local_vars</span> <span class="o">=</span> <span class="nb">locals</span><span class="p">()</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_datetime</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span>
|
||||
<span class="k">for</span> <span class="n">attr</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">attributes</span><span class="p">:</span>
|
||||
@@ -530,17 +557,21 @@
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">exif_updated</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">touched</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">converted_to_jpeg</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">aae_written</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">sidecar_json_written</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">sidecar_json_skipped</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">sidecar_exiftool_written</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">sidecar_exiftool_skipped</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">sidecar_xmp_written</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">sidecar_xmp_skipped</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">sidecar_user_written</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">sidecar_user_skipped</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">missing</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">files</span> <span class="o">+=</span> <span class="p">[</span><span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">exiftool_warning</span><span class="p">]</span>
|
||||
<span class="n">files</span> <span class="o">+=</span> <span class="p">[</span><span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">exiftool_error</span><span class="p">]</span>
|
||||
<span class="n">files</span> <span class="o">+=</span> <span class="p">[</span><span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">error</span><span class="p">]</span>
|
||||
<span class="n">files</span> <span class="o">+=</span> <span class="p">[</span><span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">sidecar_user_error</span><span class="p">]</span>
|
||||
|
||||
<span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">files</span><span class="p">))</span></div>
|
||||
|
||||
@@ -569,7 +600,7 @@
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">photo</span><span class="p">:</span> <span class="s2">"PhotoInfo"</span><span class="p">,</span> <span class="n">tmpdir</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">photo</span> <span class="o">=</span> <span class="n">photo</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_render_options</span> <span class="o">=</span> <span class="n">RenderOptions</span><span class="p">()</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_verbose</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">_verbose</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_verbose</span> <span class="o">=</span> <span class="n">photo</span><span class="o">.</span><span class="n">_verbose</span>
|
||||
|
||||
<span class="c1"># define functions for adding markup</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_filepath</span> <span class="o">=</span> <span class="n">add_rich_markup_tag</span><span class="p">(</span><span class="s2">"filepath"</span><span class="p">,</span> <span class="n">rich</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||||
@@ -666,6 +697,11 @@
|
||||
<span class="n">dest</span><span class="p">,</span> <span class="n">options</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_should_convert_to_jpeg</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span> <span class="n">options</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># stage files for export by finding path in local library or downloading from iCloud as appropriate</span>
|
||||
<span class="c1"># for `--download-missing` and `--update` case, this may cause unnecessary downloads</span>
|
||||
<span class="c1"># as it will download the file even if it's not needed (won't be checked until the _should_update_photo() call from _export_photo()</span>
|
||||
<span class="c1"># fixing this will require major refactoring of the export code, see #1086</span>
|
||||
<span class="c1"># leaving it for now as this should not be a common use case</span>
|
||||
<span class="c1"># (if using `--update` it is much better to be using "Download originals to this Mac" in Photos)</span>
|
||||
<span class="n">staged_files</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stage_photos_for_export</span><span class="p">(</span><span class="n">options</span><span class="p">)</span>
|
||||
<span class="n">src</span> <span class="o">=</span> <span class="n">staged_files</span><span class="o">.</span><span class="n">edited</span> <span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">edited</span> <span class="k">else</span> <span class="n">staged_files</span><span class="o">.</span><span class="n">original</span>
|
||||
|
||||
@@ -687,6 +723,7 @@
|
||||
<span class="sa">f</span><span class="s2">"Skipping missing </span><span class="si">{</span><span class="s1">'edited'</span> <span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">edited</span> <span class="k">else</span> <span class="s1">'original'</span><span class="si">}</span><span class="s2"> photo </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_filename</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">original_filename</span><span class="p">)</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_uuid</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span><span class="p">)</span><span class="si">}</span><span class="s2">)"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">all_results</span><span class="o">.</span><span class="n">missing</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
|
||||
<span class="n">unlock_filename</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># copy live photo associated .mov if requested</span>
|
||||
<span class="k">if</span> <span class="n">export_original</span> <span class="ow">and</span> <span class="n">options</span><span class="o">.</span><span class="n">live_photo</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">live_photo</span><span class="p">:</span>
|
||||
@@ -762,7 +799,9 @@
|
||||
<span class="n">preview_name</span> <span class="o">=</span> <span class="p">(</span>
|
||||
<span class="n">preview_name</span>
|
||||
<span class="k">if</span> <span class="nb">any</span><span class="p">([</span><span class="n">options</span><span class="o">.</span><span class="n">overwrite</span><span class="p">,</span> <span class="n">options</span><span class="o">.</span><span class="n">update</span><span class="p">,</span> <span class="n">options</span><span class="o">.</span><span class="n">force_update</span><span class="p">])</span>
|
||||
<span class="k">else</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="n">increment_filename</span><span class="p">(</span><span class="n">preview_name</span><span class="p">))</span>
|
||||
<span class="k">else</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span>
|
||||
<span class="n">increment_filename</span><span class="p">(</span><span class="n">preview_name</span><span class="p">,</span> <span class="n">lock</span><span class="o">=</span><span class="ow">not</span> <span class="n">options</span><span class="o">.</span><span class="n">dry_run</span><span class="p">)</span>
|
||||
<span class="p">)</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">all_results</span> <span class="o">+=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_export_photo</span><span class="p">(</span>
|
||||
<span class="n">preview_path</span><span class="p">,</span>
|
||||
@@ -777,6 +816,8 @@
|
||||
<span class="sa">f</span><span class="s2">"Skipping missing preview photo for </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_filename</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">original_filename</span><span class="p">)</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_uuid</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span><span class="p">)</span><span class="si">}</span><span class="s2">)"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">export_aae</span><span class="p">:</span>
|
||||
<span class="n">all_results</span> <span class="o">+=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_write_aae_file</span><span class="p">(</span><span class="n">dest</span><span class="o">=</span><span class="n">dest</span><span class="p">,</span> <span class="n">options</span><span class="o">=</span><span class="n">options</span><span class="p">)</span>
|
||||
<span class="n">all_results</span> <span class="o">+=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_write_sidecar_files</span><span class="p">(</span><span class="n">dest</span><span class="o">=</span><span class="n">dest</span><span class="p">,</span> <span class="n">options</span><span class="o">=</span><span class="n">options</span><span class="p">)</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">all_results</span></div>
|
||||
@@ -822,11 +863,10 @@
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">path_edited</span><span class="p">:</span>
|
||||
<span class="n">ext</span> <span class="o">=</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">path_edited</span><span class="p">)</span><span class="o">.</span><span class="n">suffix</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">uti</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uti_edited</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uti_edited</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uti</span>
|
||||
<span class="n">uti</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uti_edited</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uti</span>
|
||||
<span class="n">ext</span> <span class="o">=</span> <span class="n">get_preferred_uti_extension</span><span class="p">(</span><span class="n">uti</span><span class="p">)</span>
|
||||
<span class="n">ext</span> <span class="o">=</span> <span class="s2">"."</span> <span class="o">+</span> <span class="n">ext</span>
|
||||
<span class="n">edited_filename</span> <span class="o">=</span> <span class="n">original_filename</span><span class="o">.</span><span class="n">stem</span> <span class="o">+</span> <span class="s2">"_edited"</span> <span class="o">+</span> <span class="n">ext</span>
|
||||
<span class="k">return</span> <span class="n">edited_filename</span>
|
||||
<span class="n">ext</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">".</span><span class="si">{</span><span class="n">ext</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">original_filename</span><span class="o">.</span><span class="n">stem</span><span class="si">}</span><span class="s2">_edited</span><span class="si">{</span><span class="n">ext</span><span class="si">}</span><span class="s2">"</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_get_dest_path</span><span class="p">(</span>
|
||||
<span class="bp">self</span><span class="p">,</span> <span class="n">dest</span><span class="p">:</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">,</span> <span class="n">options</span><span class="p">:</span> <span class="n">ExportOptions</span>
|
||||
@@ -841,16 +881,32 @@
|
||||
<span class="sd"> new dest path (pathlib.Path)</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="c1"># lock files are used to minimize chance of name collision when in parallel mode</span>
|
||||
<span class="c1"># don't create lock files if in dry_run mode</span>
|
||||
<span class="n">lock</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">options</span><span class="o">.</span><span class="n">dry_run</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_lock_filename</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
|
||||
<span class="sd">"""Lock filename if not in dry_run mode"""</span>
|
||||
<span class="k">return</span> <span class="n">lock_filename</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span> <span class="k">if</span> <span class="n">lock</span> <span class="k">else</span> <span class="n">filename</span>
|
||||
|
||||
<span class="c1"># if overwrite==False and #increment==False, export should fail if file exists</span>
|
||||
<span class="k">if</span> <span class="n">dest</span><span class="o">.</span><span class="n">exists</span><span class="p">()</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">any</span><span class="p">(</span>
|
||||
<span class="p">[</span><span class="n">options</span><span class="o">.</span><span class="n">increment</span><span class="p">,</span> <span class="n">options</span><span class="o">.</span><span class="n">update</span><span class="p">,</span> <span class="n">options</span><span class="o">.</span><span class="n">force_update</span><span class="p">,</span> <span class="n">options</span><span class="o">.</span><span class="n">overwrite</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="p">(</span>
|
||||
<span class="ow">not</span> <span class="nb">any</span><span class="p">(</span>
|
||||
<span class="p">[</span>
|
||||
<span class="n">options</span><span class="o">.</span><span class="n">increment</span><span class="p">,</span>
|
||||
<span class="n">options</span><span class="o">.</span><span class="n">update</span><span class="p">,</span>
|
||||
<span class="n">options</span><span class="o">.</span><span class="n">force_update</span><span class="p">,</span>
|
||||
<span class="n">options</span><span class="o">.</span><span class="n">overwrite</span><span class="p">,</span>
|
||||
<span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
<span class="ow">and</span> <span class="n">dest</span><span class="o">.</span><span class="n">exists</span><span class="p">()</span>
|
||||
<span class="p">):</span>
|
||||
<span class="k">raise</span> <span class="ne">FileExistsError</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"destination exists (</span><span class="si">{</span><span class="n">dest</span><span class="si">}</span><span class="s2">); overwrite=</span><span class="si">{</span><span class="n">options</span><span class="o">.</span><span class="n">overwrite</span><span class="si">}</span><span class="s2">, increment=</span><span class="si">{</span><span class="n">options</span><span class="o">.</span><span class="n">increment</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="c1"># if overwrite, we don't care if the file exists or not</span>
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">overwrite</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">overwrite</span> <span class="ow">and</span> <span class="n">_lock_filename</span><span class="p">(</span><span class="n">dest</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="n">dest</span>
|
||||
|
||||
<span class="c1"># if not update or overwrite, check to see if file exists and if so, add (1), (2), etc</span>
|
||||
@@ -862,19 +918,21 @@
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">increment</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">any</span><span class="p">(</span>
|
||||
<span class="p">[</span><span class="n">options</span><span class="o">.</span><span class="n">update</span><span class="p">,</span> <span class="n">options</span><span class="o">.</span><span class="n">force_update</span><span class="p">,</span> <span class="n">options</span><span class="o">.</span><span class="n">overwrite</span><span class="p">]</span>
|
||||
<span class="p">):</span>
|
||||
<span class="k">return</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="n">increment_filename</span><span class="p">(</span><span class="n">dest</span><span class="p">))</span>
|
||||
<span class="k">return</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="n">increment_filename</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span> <span class="n">lock</span><span class="o">=</span><span class="n">lock</span><span class="p">))</span>
|
||||
|
||||
<span class="c1"># if update and file exists, need to check to see if it's the right file by checking export db</span>
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">update</span> <span class="ow">or</span> <span class="n">options</span><span class="o">.</span><span class="n">force_update</span><span class="p">:</span>
|
||||
<span class="n">export_db</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">export_db</span>
|
||||
<span class="n">dest_uuid</span> <span class="o">=</span> <span class="n">export_db</span><span class="o">.</span><span class="n">get_uuid_for_file</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">dest_uuid</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">dest</span><span class="o">.</span><span class="n">exists</span><span class="p">():</span>
|
||||
<span class="k">if</span> <span class="n">dest_uuid</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">dest</span><span class="o">.</span><span class="n">exists</span><span class="p">()</span> <span class="ow">and</span> <span class="n">_lock_filename</span><span class="p">(</span><span class="n">dest</span><span class="p">):</span>
|
||||
<span class="c1"># destination doesn't exist in export db and doesn't exist on disk</span>
|
||||
<span class="c1"># so we can just use it</span>
|
||||
<span class="k">return</span> <span class="n">dest</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">dest_uuid</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span><span class="p">:</span>
|
||||
<span class="c1"># destination is the right file</span>
|
||||
<span class="c1"># will use it even if locked so don't check return value of _lock_filename</span>
|
||||
<span class="n">_lock_filename</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">dest</span>
|
||||
|
||||
<span class="c1"># either dest_uuid is wrong or file exists and there's no associated UUID, so find a name that matches</span>
|
||||
@@ -883,24 +941,35 @@
|
||||
<span class="c1"># first, find all matching files in export db and see if there's a match</span>
|
||||
<span class="k">if</span> <span class="n">dest_target</span> <span class="o">:=</span> <span class="n">export_db</span><span class="o">.</span><span class="n">get_target_for_file</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span><span class="p">,</span> <span class="n">dest</span><span class="p">):</span>
|
||||
<span class="c1"># there's a match so use that</span>
|
||||
<span class="n">_lock_filename</span><span class="p">(</span><span class="n">dest_target</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="n">dest_target</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># no match so need to create a new name</span>
|
||||
<span class="c1"># increment the destination file until we find one that doesn't exist and doesn't match another uuid in the database</span>
|
||||
<span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>
|
||||
<span class="n">dest</span><span class="p">,</span> <span class="n">count</span> <span class="o">=</span> <span class="n">increment_filename_with_count</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span> <span class="n">count</span><span class="p">)</span>
|
||||
<span class="n">dest</span><span class="p">,</span> <span class="n">count</span> <span class="o">=</span> <span class="n">increment_filename_with_count</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span> <span class="n">count</span><span class="p">,</span> <span class="n">lock</span><span class="o">=</span><span class="n">lock</span><span class="p">)</span>
|
||||
<span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
|
||||
<span class="k">while</span> <span class="n">export_db</span><span class="o">.</span><span class="n">get_uuid_for_file</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="n">dest</span><span class="p">,</span> <span class="n">count</span> <span class="o">=</span> <span class="n">increment_filename_with_count</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span> <span class="n">count</span><span class="p">)</span>
|
||||
<span class="n">dest</span><span class="p">,</span> <span class="n">count</span> <span class="o">=</span> <span class="n">increment_filename_with_count</span><span class="p">(</span><span class="n">dest</span><span class="p">,</span> <span class="n">count</span><span class="p">,</span> <span class="n">lock</span><span class="o">=</span><span class="n">lock</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># fail safe...I can't think of a case that gets here</span>
|
||||
<span class="n">_lock_filename</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">dest</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_should_update_photo</span><span class="p">(</span>
|
||||
<span class="bp">self</span><span class="p">,</span> <span class="n">src</span><span class="p">:</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">,</span> <span class="n">dest</span><span class="p">:</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">,</span> <span class="n">options</span><span class="p">:</span> <span class="n">ExportOptions</span>
|
||||
<span class="p">)</span> <span class="o">-></span> <span class="n">t</span><span class="o">.</span><span class="n">Literal</span><span class="p">[</span><span class="kc">True</span><span class="p">,</span> <span class="kc">False</span><span class="p">]:</span>
|
||||
<span class="sd">"""Return True if photo should be updated, else False"""</span>
|
||||
<span class="bp">self</span><span class="p">,</span> <span class="n">src</span><span class="p">:</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span> <span class="o">|</span> <span class="kc">None</span><span class="p">,</span> <span class="n">dest</span><span class="p">:</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">,</span> <span class="n">options</span><span class="p">:</span> <span class="n">ExportOptions</span>
|
||||
<span class="p">)</span> <span class="o">-></span> <span class="nb">bool</span> <span class="o">|</span> <span class="n">ShouldUpdate</span><span class="p">:</span>
|
||||
<span class="sd">"""Return True if photo should be updated, else False</span>
|
||||
|
||||
<span class="sd"> Args:</span>
|
||||
<span class="sd"> src (pathlib.Path | None): source path; if None, photo is missing and</span>
|
||||
<span class="sd"> any checks that require src will return True</span>
|
||||
<span class="sd"> dest (pathlib.Path): destination path</span>
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> False if photo should not be updated otherwise a truthy ShouldUpdate value</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="c1"># NOTE: The order of certain checks is important</span>
|
||||
<span class="c1"># read the comments below to understand why before changing</span>
|
||||
@@ -914,11 +983,11 @@
|
||||
<span class="c1"># photo doesn't exist in database, should update</span>
|
||||
<span class="k">return</span> <span class="n">ShouldUpdate</span><span class="o">.</span><span class="n">NOT_IN_DATABASE</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">export_as_hardlink</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">dest</span><span class="o">.</span><span class="n">samefile</span><span class="p">(</span><span class="n">src</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">export_as_hardlink</span> <span class="ow">and</span> <span class="p">(</span><span class="ow">not</span> <span class="n">src</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">dest</span><span class="o">.</span><span class="n">samefile</span><span class="p">(</span><span class="n">src</span><span class="p">)):</span>
|
||||
<span class="c1"># different files, should update</span>
|
||||
<span class="k">return</span> <span class="n">ShouldUpdate</span><span class="o">.</span><span class="n">HARDLINK_DIFFERENT_FILES</span>
|
||||
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">options</span><span class="o">.</span><span class="n">export_as_hardlink</span> <span class="ow">and</span> <span class="n">dest</span><span class="o">.</span><span class="n">samefile</span><span class="p">(</span><span class="n">src</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">options</span><span class="o">.</span><span class="n">export_as_hardlink</span> <span class="ow">and</span> <span class="p">(</span><span class="ow">not</span> <span class="n">src</span> <span class="ow">or</span> <span class="n">dest</span><span class="o">.</span><span class="n">samefile</span><span class="p">(</span><span class="n">src</span><span class="p">)):</span>
|
||||
<span class="c1"># same file but not exporting as hardlink, should update</span>
|
||||
<span class="k">return</span> <span class="n">ShouldUpdate</span><span class="o">.</span><span class="n">NOT_HARDLINK_SAME_FILES</span>
|
||||
|
||||
@@ -950,7 +1019,9 @@
|
||||
<span class="c1"># as exiftool will be used to update edited file</span>
|
||||
<span class="k">return</span> <span class="n">ShouldUpdate</span><span class="o">.</span><span class="n">EXIFTOOL_DIFFERENT</span> <span class="k">if</span> <span class="n">rv</span> <span class="k">else</span> <span class="kc">False</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">edited</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">fileutil</span><span class="o">.</span><span class="n">cmp_file_sig</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">file_record</span><span class="o">.</span><span class="n">src_sig</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">edited</span> <span class="ow">and</span> <span class="p">(</span>
|
||||
<span class="ow">not</span> <span class="n">src</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">fileutil</span><span class="o">.</span><span class="n">cmp_file_sig</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">file_record</span><span class="o">.</span><span class="n">src_sig</span><span class="p">)</span>
|
||||
<span class="p">):</span>
|
||||
<span class="c1"># edited file in Photos doesn't match what was last exported</span>
|
||||
<span class="k">return</span> <span class="n">ShouldUpdate</span><span class="o">.</span><span class="n">EDITED_SIG_DIFFERENT</span>
|
||||
|
||||
@@ -1001,22 +1072,46 @@
|
||||
|
||||
<span class="c1"># download any missing files</span>
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">download_missing</span><span class="p">:</span>
|
||||
<span class="n">live_photo</span> <span class="o">=</span> <span class="n">staged</span><span class="o">.</span><span class="n">edited_live</span> <span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">edited</span> <span class="k">else</span> <span class="n">staged</span><span class="o">.</span><span class="n">original_live</span>
|
||||
<span class="n">missing_options</span> <span class="o">=</span> <span class="n">ExportOptions</span><span class="p">(</span>
|
||||
<span class="n">edited</span><span class="o">=</span><span class="n">options</span><span class="o">.</span><span class="n">edited</span><span class="p">,</span>
|
||||
<span class="n">preview</span><span class="o">=</span><span class="n">options</span><span class="o">.</span><span class="n">preview</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">staged</span><span class="o">.</span><span class="n">preview</span><span class="p">,</span>
|
||||
<span class="n">raw_photo</span><span class="o">=</span><span class="n">options</span><span class="o">.</span><span class="n">raw_photo</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">staged</span><span class="o">.</span><span class="n">raw</span><span class="p">,</span>
|
||||
<span class="n">live_photo</span><span class="o">=</span><span class="n">options</span><span class="o">.</span><span class="n">live_photo</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">live_photo</span><span class="p">,</span>
|
||||
<span class="n">staged</span> <span class="o">|=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stage_missing_photos_for_export</span><span class="p">(</span>
|
||||
<span class="n">staged</span><span class="o">=</span><span class="n">staged</span><span class="p">,</span> <span class="n">options</span><span class="o">=</span><span class="n">options</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">use_photokit</span><span class="p">:</span>
|
||||
<span class="n">missing_staged</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stage_photo_for_export_with_photokit</span><span class="p">(</span>
|
||||
<span class="n">options</span><span class="o">=</span><span class="n">missing_options</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">missing_staged</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stage_photo_for_export_with_applescript</span><span class="p">(</span>
|
||||
<span class="n">options</span><span class="o">=</span><span class="n">missing_options</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">staged</span> <span class="o">|=</span> <span class="n">missing_staged</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">staged</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_stage_missing_photos_for_export</span><span class="p">(</span>
|
||||
<span class="bp">self</span><span class="p">,</span> <span class="n">staged</span><span class="p">:</span> <span class="n">StagedFiles</span><span class="p">,</span> <span class="n">options</span><span class="p">:</span> <span class="n">ExportOptions</span>
|
||||
<span class="p">)</span> <span class="o">-></span> <span class="n">StagedFiles</span><span class="p">:</span>
|
||||
<span class="sd">"""Download and stage any missing files for export"""</span>
|
||||
|
||||
<span class="c1"># if live photo and requesting edited version need the edited live photo</span>
|
||||
<span class="n">live_photo</span> <span class="o">=</span> <span class="n">staged</span><span class="o">.</span><span class="n">edited_live</span> <span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">edited</span> <span class="k">else</span> <span class="n">staged</span><span class="o">.</span><span class="n">original_live</span>
|
||||
|
||||
<span class="c1"># is there actually a missing file? (#1086)</span>
|
||||
<span class="n">something_to_download</span> <span class="o">=</span> <span class="p">(</span>
|
||||
<span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">hasadjustments</span> <span class="ow">and</span> <span class="n">options</span><span class="o">.</span><span class="n">edited</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">staged</span><span class="o">.</span><span class="n">edited</span><span class="p">)</span>
|
||||
<span class="ow">or</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">live_photo</span> <span class="ow">and</span> <span class="n">options</span><span class="o">.</span><span class="n">live_photo</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">live_photo</span><span class="p">)</span>
|
||||
<span class="ow">or</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">has_raw</span> <span class="ow">and</span> <span class="n">options</span><span class="o">.</span><span class="n">raw_photo</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">staged</span><span class="o">.</span><span class="n">raw</span><span class="p">)</span>
|
||||
<span class="ow">or</span> <span class="p">(</span><span class="n">options</span><span class="o">.</span><span class="n">preview</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">staged</span><span class="o">.</span><span class="n">preview</span><span class="p">)</span>
|
||||
<span class="ow">or</span> <span class="p">(</span><span class="ow">not</span> <span class="n">options</span><span class="o">.</span><span class="n">edited</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">staged</span><span class="o">.</span><span class="n">original</span><span class="p">)</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">something_to_download</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="n">staged</span>
|
||||
|
||||
<span class="n">missing_options</span> <span class="o">=</span> <span class="n">ExportOptions</span><span class="p">(</span>
|
||||
<span class="n">edited</span><span class="o">=</span><span class="n">options</span><span class="o">.</span><span class="n">edited</span><span class="p">,</span>
|
||||
<span class="n">preview</span><span class="o">=</span><span class="n">options</span><span class="o">.</span><span class="n">preview</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">staged</span><span class="o">.</span><span class="n">preview</span><span class="p">,</span>
|
||||
<span class="n">raw_photo</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">has_raw</span> <span class="ow">and</span> <span class="n">options</span><span class="o">.</span><span class="n">raw_photo</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">staged</span><span class="o">.</span><span class="n">raw</span><span class="p">,</span>
|
||||
<span class="n">live_photo</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">live_photo</span> <span class="ow">and</span> <span class="n">options</span><span class="o">.</span><span class="n">live_photo</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">live_photo</span><span class="p">,</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">use_photokit</span><span class="p">:</span>
|
||||
<span class="n">missing_staged</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stage_photo_for_export_with_photokit</span><span class="p">(</span>
|
||||
<span class="n">options</span><span class="o">=</span><span class="n">missing_options</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">missing_staged</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stage_photo_for_export_with_applescript</span><span class="p">(</span>
|
||||
<span class="n">options</span><span class="o">=</span><span class="n">missing_options</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">staged</span> <span class="o">|=</span> <span class="n">missing_staged</span>
|
||||
<span class="k">return</span> <span class="n">staged</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_stage_photo_for_export_with_photokit</span><span class="p">(</span>
|
||||
@@ -1131,7 +1226,8 @@
|
||||
<span class="sd">"""Stage a photo for export with AppleScript to a temporary directory</span>
|
||||
|
||||
<span class="sd"> Note: If exporting an edited live photo, the associated live video will not be exported.</span>
|
||||
<span class="sd"> This is a limitation of the Photos AppleScript interface and Photos behaves the same way."""</span>
|
||||
<span class="sd"> This is a limitation of the Photos AppleScript interface and Photos behaves the same way.</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">edited</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">hasadjustments</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Edited version requested but photo has no adjustments"</span><span class="p">)</span>
|
||||
@@ -1360,7 +1456,7 @@
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">fileutil</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">dest_str</span><span class="p">)</span>
|
||||
<span class="n">verbose</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Exported </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_filename</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">original_filename</span><span class="p">)</span><span class="si">}</span><span class="s2"> to </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_filepath</span><span class="p">(</span><span class="n">dest_str</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="sa">f</span><span class="s2">"Exported </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_filename</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">original_filename</span><span class="p">)</span><span class="si">}</span><span class="s2"> to </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_filepath</span><span class="p">(</span><span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">dest_str</span><span class="p">))</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="n">ExportError</span><span class="p">(</span>
|
||||
@@ -1391,7 +1487,7 @@
|
||||
|
||||
<span class="c1"># set data in the database</span>
|
||||
<span class="k">with</span> <span class="n">export_db</span><span class="o">.</span><span class="n">create_or_get_file_record</span><span class="p">(</span><span class="n">dest_str</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span><span class="p">)</span> <span class="k">as</span> <span class="n">rec</span><span class="p">:</span>
|
||||
<span class="n">rec</span><span class="o">.</span><span class="n">photoinfo</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
|
||||
<span class="n">rec</span><span class="o">.</span><span class="n">photoinfo</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">json</span><span class="p">(</span><span class="n">shallow</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||
<span class="n">rec</span><span class="o">.</span><span class="n">export_options</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">bit_flags</span>
|
||||
<span class="c1"># don't set src_sig as that is set above before any modifications by convert_to_jpeg or exiftool</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">options</span><span class="o">.</span><span class="n">ignore_signature</span><span class="p">:</span>
|
||||
@@ -1413,6 +1509,9 @@
|
||||
<span class="s2">"exiftool_warning"</span><span class="p">:</span> <span class="n">exif_results</span><span class="o">.</span><span class="n">exiftool_warning</span><span class="p">,</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="c1"># clean up lock file</span>
|
||||
<span class="n">unlock_filename</span><span class="p">(</span><span class="n">dest_str</span><span class="p">)</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">results</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_export_photo_uuid_applescript</span><span class="p">(</span>
|
||||
@@ -1518,6 +1617,54 @@
|
||||
<span class="n">exported_paths</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">dest_new</span><span class="p">))</span>
|
||||
<span class="k">return</span> <span class="n">exported_paths</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_write_aae_file</span><span class="p">(</span>
|
||||
<span class="bp">self</span><span class="p">,</span>
|
||||
<span class="n">dest</span><span class="p">:</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">,</span>
|
||||
<span class="n">options</span><span class="p">:</span> <span class="n">ExportOptions</span><span class="p">,</span>
|
||||
<span class="p">)</span> <span class="o">-></span> <span class="n">ExportResults</span><span class="p">:</span>
|
||||
<span class="sd">"""Write AAE file for the photo."""</span>
|
||||
|
||||
<span class="c1"># AAE files describe adjustments to originals, so they don't make sense</span>
|
||||
<span class="c1"># for edited files</span>
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">edited</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="n">ExportResults</span><span class="p">()</span>
|
||||
|
||||
<span class="n">verbose</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">verbose</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">_verbose</span>
|
||||
|
||||
<span class="n">aae_src</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">adjustments_path</span>
|
||||
<span class="k">if</span> <span class="n">aae_src</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="n">ExportResults</span><span class="p">()</span>
|
||||
<span class="n">aae_dest</span> <span class="o">=</span> <span class="n">dest</span><span class="o">.</span><span class="n">with_suffix</span><span class="p">(</span><span class="s2">".AAE"</span><span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">export_as_hardlink</span><span class="p">:</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="n">aae_dest</span><span class="o">.</span><span class="n">exists</span><span class="p">()</span> <span class="ow">and</span> <span class="nb">any</span><span class="p">(</span>
|
||||
<span class="p">[</span><span class="n">options</span><span class="o">.</span><span class="n">overwrite</span><span class="p">,</span> <span class="n">options</span><span class="o">.</span><span class="n">update</span><span class="p">,</span> <span class="n">options</span><span class="o">.</span><span class="n">force_update</span><span class="p">]</span>
|
||||
<span class="p">):</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">options</span><span class="o">.</span><span class="n">fileutil</span><span class="o">.</span><span class="n">unlink</span><span class="p">(</span><span class="n">aae_dest</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="n">ExportError</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Error removing file </span><span class="si">{</span><span class="n">aae_dest</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2"> ((</span><span class="si">{</span><span class="n">lineno</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)</span><span class="si">}</span><span class="s2">)"</span>
|
||||
<span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
||||
<span class="n">options</span><span class="o">.</span><span class="n">fileutil</span><span class="o">.</span><span class="n">hardlink</span><span class="p">(</span><span class="n">aae_src</span><span class="p">,</span> <span class="n">aae_dest</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="n">ExportError</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Error hardlinking </span><span class="si">{</span><span class="n">aae_src</span><span class="si">}</span><span class="s2"> to </span><span class="si">{</span><span class="n">aae_dest</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="n">lineno</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)</span><span class="si">}</span><span class="s2">)"</span>
|
||||
<span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">options</span><span class="o">.</span><span class="n">fileutil</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">aae_src</span><span class="p">,</span> <span class="n">aae_dest</span><span class="p">)</span>
|
||||
<span class="n">verbose</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Exported adjustments of </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_filename</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">original_filename</span><span class="p">)</span><span class="si">}</span><span class="s2"> to </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_filepath</span><span class="p">(</span><span class="n">normalize_fs_path</span><span class="p">(</span><span class="n">aae_dest</span><span class="p">))</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="n">ExportError</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Error copying file </span><span class="si">{</span><span class="n">aae_src</span><span class="si">}</span><span class="s2"> to </span><span class="si">{</span><span class="n">aae_dest</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="n">lineno</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)</span><span class="si">}</span><span class="s2">)"</span>
|
||||
<span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">ExportResults</span><span class="p">(</span><span class="n">aae_written</span><span class="o">=</span><span class="p">[</span><span class="n">aae_dest</span><span class="p">])</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_write_sidecar_files</span><span class="p">(</span>
|
||||
<span class="bp">self</span><span class="p">,</span>
|
||||
<span class="n">dest</span><span class="p">:</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">,</span>
|
||||
@@ -1697,10 +1844,10 @@
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">options</span><span class="o">.</span><span class="n">dry_run</span><span class="p">:</span>
|
||||
<span class="n">warning_</span><span class="p">,</span> <span class="n">error_</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_write_exif_data</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">options</span><span class="o">=</span><span class="n">options</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">warning_</span><span class="p">:</span>
|
||||
<span class="n">exiftool_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">dest</span><span class="p">,</span> <span class="n">warning_</span><span class="p">))</span>
|
||||
<span class="n">exiftool_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="nb">str</span><span class="p">(</span><span class="n">dest</span><span class="p">),</span> <span class="nb">str</span><span class="p">(</span><span class="n">warning_</span><span class="p">)))</span>
|
||||
<span class="k">if</span> <span class="n">error_</span><span class="p">:</span>
|
||||
<span class="n">exiftool_results</span><span class="o">.</span><span class="n">exiftool_error</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">dest</span><span class="p">,</span> <span class="n">error_</span><span class="p">))</span>
|
||||
<span class="n">exiftool_results</span><span class="o">.</span><span class="n">error</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">dest</span><span class="p">,</span> <span class="n">error_</span><span class="p">))</span>
|
||||
<span class="n">exiftool_results</span><span class="o">.</span><span class="n">exiftool_error</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="nb">str</span><span class="p">(</span><span class="n">dest</span><span class="p">),</span> <span class="nb">str</span><span class="p">(</span><span class="n">error_</span><span class="p">)))</span>
|
||||
<span class="n">exiftool_results</span><span class="o">.</span><span class="n">error</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="nb">str</span><span class="p">(</span><span class="n">dest</span><span class="p">),</span> <span class="nb">str</span><span class="p">(</span><span class="n">error_</span><span class="p">)))</span>
|
||||
|
||||
<span class="n">exiftool_results</span><span class="o">.</span><span class="n">exif_updated</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
|
||||
<span class="n">exiftool_results</span><span class="o">.</span><span class="n">to_touch</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
|
||||
@@ -1742,7 +1889,7 @@
|
||||
<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">options</span><span class="o">.</span><span class="n">exiftool_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">photo</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="n">exiftool</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">_exiftool_path</span><span class="p">,</span>
|
||||
<span class="p">)</span> <span class="k">as</span> <span class="n">exiftool</span><span class="p">:</span>
|
||||
<span class="k">for</span> <span class="n">exiftag</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">exif_info</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">list</span><span class="p">:</span>
|
||||
@@ -1922,7 +2069,6 @@
|
||||
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</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">"Keys:GPSCoordinates"</span><span class="p">]</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"</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">"</span>
|
||||
<span class="n">exif</span><span class="p">[</span><span class="s2">"UserData:GPSCoordinates"</span><span class="p">]</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"</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">"</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"># [EXIF] Modify Date : 2020:10:30 00:00:00</span>
|
||||
@@ -2032,7 +2178,7 @@
|
||||
<span class="k">def</span> <span class="nf">_get_exif_keywords</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""returns list of keywords found in the file's exif metadata"""</span>
|
||||
<span class="n">keywords</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="n">exif</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">exiftool</span>
|
||||
<span class="n">exif</span> <span class="o">=</span> <span class="n">exiftool_caching</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">exif</span><span class="p">:</span>
|
||||
<span class="n">exifdict</span> <span class="o">=</span> <span class="n">exif</span><span class="o">.</span><span class="n">asdict</span><span class="p">()</span>
|
||||
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"IPTC:Keywords"</span><span class="p">,</span> <span class="s2">"XMP:TagsList"</span><span class="p">,</span> <span class="s2">"XMP:Subject"</span><span class="p">]:</span>
|
||||
@@ -2049,7 +2195,7 @@
|
||||
<span class="k">def</span> <span class="nf">_get_exif_persons</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""returns list of persons found in the file's exif metadata"""</span>
|
||||
<span class="n">persons</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="n">exif</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">exiftool</span>
|
||||
<span class="n">exif</span> <span class="o">=</span> <span class="n">exiftool_caching</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">exif</span><span class="p">:</span>
|
||||
<span class="n">exifdict</span> <span class="o">=</span> <span class="n">exif</span><span class="o">.</span><span class="n">asdict</span><span class="p">()</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
@@ -2130,10 +2276,7 @@
|
||||
|
||||
<span class="n">options</span> <span class="o">=</span> <span class="n">options</span> <span class="ow">or</span> <span class="n">ExportOptions</span><span class="p">()</span>
|
||||
|
||||
<span class="n">xmp_template_file</span> <span class="o">=</span> <span class="p">(</span>
|
||||
<span class="n">_XMP_TEMPLATE_NAME</span> <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_beta</span> <span class="k">else</span> <span class="n">_XMP_TEMPLATE_NAME_BETA</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">xmp_template</span> <span class="o">=</span> <span class="n">Template</span><span class="p">(</span><span class="n">filename</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">_TEMPLATE_DIR</span><span class="p">,</span> <span class="n">xmp_template_file</span><span class="p">))</span>
|
||||
<span class="n">xmp_template</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_xmp_template</span><span class="p">()</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">extension</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="n">extension</span> <span class="o">=</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">original_filename</span><span class="p">)</span>
|
||||
@@ -2240,6 +2383,20 @@
|
||||
<span class="n">xmp_str</span> <span class="o">=</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">line</span> <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">xmp_str</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span> <span class="k">if</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="o">!=</span> <span class="s2">""</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">xmp_str</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_xmp_template</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return the mako template for XMP sidecar, creating it if necessary"""</span>
|
||||
<span class="k">global</span> <span class="n">_global_xmp_template</span>
|
||||
<span class="k">if</span> <span class="n">_global_xmp_template</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="n">_global_xmp_template</span>
|
||||
|
||||
<span class="n">xmp_template_file</span> <span class="o">=</span> <span class="p">(</span>
|
||||
<span class="n">_XMP_TEMPLATE_NAME_BETA</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_beta</span> <span class="k">else</span> <span class="n">_XMP_TEMPLATE_NAME</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">_global_xmp_template</span> <span class="o">=</span> <span class="n">Template</span><span class="p">(</span>
|
||||
<span class="n">filename</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">_TEMPLATE_DIR</span><span class="p">,</span> <span class="n">xmp_template_file</span><span class="p">)</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">_global_xmp_template</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_write_sidecar</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="n">sidecar_str</span><span class="p">):</span>
|
||||
<span class="sd">"""write sidecar_str to filename</span>
|
||||
<span class="sd"> used for exporting sidecar info"""</span>
|
||||
@@ -2320,6 +2477,35 @@
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">new_files</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">new_files</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">exiftool_caching</span><span class="p">(</span><span class="n">photo</span><span class="p">:</span> <span class="n">SimpleNamespace</span><span class="p">)</span> <span class="o">-></span> <span class="n">ExifToolCaching</span><span class="p">:</span>
|
||||
<span class="sd">"""Return ExifToolCaching object for photo</span>
|
||||
|
||||
<span class="sd"> Args:</span>
|
||||
<span class="sd"> photo: SimpleNamespace object with photo info</span>
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> ExifToolCaching object</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="n">photo</span><span class="o">.</span><span class="n">_exiftool_caching</span>
|
||||
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">exiftool_path</span> <span class="o">=</span> <span class="n">photo</span><span class="o">.</span><span class="n">_exiftool_path</span> <span class="ow">or</span> <span class="n">get_exiftool_path</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="n">photo</span><span class="o">.</span><span class="n">path</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isfile</span><span class="p">(</span><span class="n">photo</span><span class="o">.</span><span class="n">path</span><span class="p">):</span>
|
||||
<span class="n">exiftool</span> <span class="o">=</span> <span class="n">ExifToolCaching</span><span class="p">(</span><span class="n">photo</span><span class="o">.</span><span class="n">path</span><span class="p">,</span> <span class="n">exiftool</span><span class="o">=</span><span class="n">exiftool_path</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">exiftool</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="k">except</span> <span class="ne">FileNotFoundError</span><span class="p">:</span>
|
||||
<span class="c1"># get_exiftool_path raises FileNotFoundError if exiftool not found</span>
|
||||
<span class="n">exiftool</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
|
||||
<span class="s2">"exiftool not in path; download and install from https://exiftool.org/"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="n">photo</span><span class="o">.</span><span class="n">_exiftool_caching</span> <span class="o">=</span> <span class="n">exiftool</span>
|
||||
<span class="k">return</span> <span class="n">photo</span><span class="o">.</span><span class="n">_exiftool_caching</span>
|
||||
</pre></div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,13 @@
|
||||
<!doctype html>
|
||||
<html class="no-js">
|
||||
<html class="no-js" lang="en">
|
||||
<head><meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
|
||||
<title>osxphotos.photosalbum - osxphotos 0.51.7 documentation</title>
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.photosalbum - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=68f4518137b9aefe99b631505a2064c3c42c9852" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.51.7 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.51.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -179,7 +179,8 @@
|
||||
</svg>
|
||||
<span>Back to top</span>
|
||||
</a>
|
||||
<div class="content-icon-container"><div class="theme-toggle-container theme-toggle-content">
|
||||
<div class="content-icon-container">
|
||||
<div class="theme-toggle-container theme-toggle-content">
|
||||
<button class="theme-toggle">
|
||||
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
|
||||
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||||
@@ -194,34 +195,58 @@
|
||||
</div>
|
||||
<article role="main">
|
||||
<h1>Source code for osxphotos.photosalbum</h1><div class="highlight"><pre>
|
||||
<span></span><span class="sd">""" PhotosAlbum class to create an album in default Photos library and add photos to it """</span>
|
||||
<span></span><span class="sd">""" PhotosAlbum class to create an album in default Photos library and add photos to it """</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">annotations</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">unicodedata</span>
|
||||
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Optional</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">photoscript</span>
|
||||
<span class="kn">from</span> <span class="nn">more_itertools</span> <span class="kn">import</span> <span class="n">chunked</span>
|
||||
<span class="kn">from</span> <span class="nn">photoscript</span> <span class="kn">import</span> <span class="n">Album</span><span class="p">,</span> <span class="n">Folder</span><span class="p">,</span> <span class="n">Photo</span><span class="p">,</span> <span class="n">PhotosLibrary</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">.photoinfo</span> <span class="kn">import</span> <span class="n">PhotoInfo</span>
|
||||
<span class="kn">from</span> <span class="nn">.platform</span> <span class="kn">import</span> <span class="n">assert_macos</span>
|
||||
<span class="kn">from</span> <span class="nn">.utils</span> <span class="kn">import</span> <span class="n">noop</span><span class="p">,</span> <span class="n">pluralize</span>
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"PhotosAlbum"</span><span class="p">,</span> <span class="s2">"PhotosAlbumPhotoScript"</span><span class="p">]</span>
|
||||
<span class="n">assert_macos</span><span class="p">()</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">photoscript</span>
|
||||
<span class="kn">from</span> <span class="nn">photoscript</span> <span class="kn">import</span> <span class="n">Album</span><span class="p">,</span> <span class="n">Folder</span><span class="p">,</span> <span class="n">Photo</span><span class="p">,</span> <span class="n">PhotosLibrary</span>
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"PhotosAlbum"</span><span class="p">,</span> <span class="s2">"PhotosAlbumPhotoScript"</span><span class="p">]</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">get_unicode_variants</span><span class="p">(</span><span class="n">s</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">list</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
|
||||
<span class="sd">"""Get all unicode variants of string"""</span>
|
||||
<span class="n">variants</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="n">form</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"NFC"</span><span class="p">,</span> <span class="s2">"NFD"</span><span class="p">,</span> <span class="s2">"NFKC"</span><span class="p">,</span> <span class="s2">"NFKD"</span><span class="p">]:</span>
|
||||
<span class="n">normalized</span> <span class="o">=</span> <span class="n">unicodedata</span><span class="o">.</span><span class="n">normalize</span><span class="p">(</span><span class="n">form</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span>
|
||||
<span class="n">variants</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">normalized</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">variants</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">folder_by_path</span><span class="p">(</span><span class="n">folders</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span> <span class="n">verbose</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">callable</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-></span> <span class="n">Folder</span><span class="p">:</span>
|
||||
<span class="sd">"""Get (and create if necessary) a Photos Folder by path (passed as list of folder names)"""</span>
|
||||
<span class="sd">"""Get (and create if necessary) a Photos Folder by path (passed as list of folder names)"""</span>
|
||||
<span class="n">library</span> <span class="o">=</span> <span class="n">PhotosLibrary</span><span class="p">()</span>
|
||||
<span class="n">verbose</span> <span class="o">=</span> <span class="n">verbose</span> <span class="ow">or</span> <span class="n">noop</span>
|
||||
<span class="n">top_folder_name</span> <span class="o">=</span> <span class="n">folders</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
|
||||
<span class="n">top_folder</span> <span class="o">=</span> <span class="n">library</span><span class="o">.</span><span class="n">folder</span><span class="p">(</span><span class="n">top_folder_name</span><span class="p">,</span> <span class="n">top_level</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">top_folder</span><span class="p">:</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Creating folder '</span><span class="si">{</span><span class="n">top_folder_name</span><span class="si">}</span><span class="s2">'"</span><span class="p">)</span>
|
||||
|
||||
<span class="k">for</span> <span class="n">folder_variant</span> <span class="ow">in</span> <span class="n">get_unicode_variants</span><span class="p">(</span><span class="n">top_folder_name</span><span class="p">):</span>
|
||||
<span class="n">top_folder</span> <span class="o">=</span> <span class="n">library</span><span class="o">.</span><span class="n">folder</span><span class="p">(</span><span class="n">folder_variant</span><span class="p">,</span> <span class="n">top_level</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">top_folder</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Creating folder '</span><span class="si">{</span><span class="n">top_folder_name</span><span class="si">}</span><span class="s2">'"</span><span class="p">)</span>
|
||||
<span class="n">top_folder</span> <span class="o">=</span> <span class="n">library</span><span class="o">.</span><span class="n">create_folder</span><span class="p">(</span><span class="n">top_folder_name</span><span class="p">)</span>
|
||||
|
||||
<span class="n">current_folder</span> <span class="o">=</span> <span class="n">top_folder</span>
|
||||
<span class="k">for</span> <span class="n">folder_name</span> <span class="ow">in</span> <span class="n">folders</span><span class="p">:</span>
|
||||
<span class="n">folder</span> <span class="o">=</span> <span class="n">current_folder</span><span class="o">.</span><span class="n">folder</span><span class="p">(</span><span class="n">folder_name</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">folder</span><span class="p">:</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Creating folder '</span><span class="si">{</span><span class="n">folder_name</span><span class="si">}</span><span class="s2">'"</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">folder_variant</span> <span class="ow">in</span> <span class="n">get_unicode_variants</span><span class="p">(</span><span class="n">folder_name</span><span class="p">):</span>
|
||||
<span class="n">folder</span> <span class="o">=</span> <span class="n">current_folder</span><span class="o">.</span><span class="n">folder</span><span class="p">(</span><span class="n">folder_variant</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">folder</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Creating folder '</span><span class="si">{</span><span class="n">folder_name</span><span class="si">}</span><span class="s2">'"</span><span class="p">)</span>
|
||||
<span class="n">folder</span> <span class="o">=</span> <span class="n">current_folder</span><span class="o">.</span><span class="n">create_folder</span><span class="p">(</span><span class="n">folder_name</span><span class="p">)</span>
|
||||
<span class="n">current_folder</span> <span class="o">=</span> <span class="n">folder</span>
|
||||
<span class="k">return</span> <span class="n">current_folder</span>
|
||||
@@ -230,30 +255,39 @@
|
||||
<span class="k">def</span> <span class="nf">album_by_path</span><span class="p">(</span>
|
||||
<span class="n">folders_album</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span> <span class="n">verbose</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">callable</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="p">)</span> <span class="o">-></span> <span class="n">Album</span><span class="p">:</span>
|
||||
<span class="sd">"""Get (and create if necessary) a Photos Album by path (pass as list of folders, album name)"""</span>
|
||||
<span class="sd">"""Get (and create if necessary) a Photos Album by path (pass as list of folders, album name)"""</span>
|
||||
<span class="n">library</span> <span class="o">=</span> <span class="n">PhotosLibrary</span><span class="p">()</span>
|
||||
<span class="n">verbose</span> <span class="o">=</span> <span class="n">verbose</span> <span class="ow">or</span> <span class="n">noop</span>
|
||||
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">folders_album</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
||||
<span class="c1"># have folders</span>
|
||||
<span class="n">album_name</span> <span class="o">=</span> <span class="n">folders_album</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
|
||||
<span class="n">folder</span> <span class="o">=</span> <span class="n">folder_by_path</span><span class="p">(</span><span class="n">folders_album</span><span class="p">,</span> <span class="n">verbose</span><span class="p">)</span>
|
||||
<span class="n">album</span> <span class="o">=</span> <span class="n">folder</span><span class="o">.</span><span class="n">album</span><span class="p">(</span><span class="n">album_name</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">album</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Creating album '</span><span class="si">{</span><span class="n">album_name</span><span class="si">}</span><span class="s2">'"</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">album_variant</span> <span class="ow">in</span> <span class="n">get_unicode_variants</span><span class="p">(</span><span class="n">album_name</span><span class="p">):</span>
|
||||
<span class="c1"># Get album if it exists</span>
|
||||
<span class="c1"># need to check every unicode variant to avoid creating duplicate albums with same visual representation (#1085)</span>
|
||||
<span class="n">album</span> <span class="o">=</span> <span class="n">folder</span><span class="o">.</span><span class="n">album</span><span class="p">(</span><span class="n">album_variant</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">album</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Creating album '</span><span class="si">{</span><span class="n">album_name</span><span class="si">}</span><span class="s2">'"</span><span class="p">)</span>
|
||||
<span class="n">album</span> <span class="o">=</span> <span class="n">folder</span><span class="o">.</span><span class="n">create_album</span><span class="p">(</span><span class="n">album_name</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="c1"># only have album name</span>
|
||||
<span class="n">album_name</span> <span class="o">=</span> <span class="n">folders_album</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="n">album</span> <span class="o">=</span> <span class="n">library</span><span class="o">.</span><span class="n">album</span><span class="p">(</span><span class="n">album_name</span><span class="p">,</span> <span class="n">top_level</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">album</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Creating album '</span><span class="si">{</span><span class="n">album_name</span><span class="si">}</span><span class="s2">'"</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">album_variant</span> <span class="ow">in</span> <span class="n">get_unicode_variants</span><span class="p">(</span><span class="n">album_name</span><span class="p">):</span>
|
||||
<span class="n">album</span> <span class="o">=</span> <span class="n">library</span><span class="o">.</span><span class="n">album</span><span class="p">(</span><span class="n">album_variant</span><span class="p">,</span> <span class="n">top_level</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">album</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="c1"># album doesn't exist, create it</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Creating album '</span><span class="si">{</span><span class="n">album_name</span><span class="si">}</span><span class="s2">'"</span><span class="p">)</span>
|
||||
<span class="n">album</span> <span class="o">=</span> <span class="n">library</span><span class="o">.</span><span class="n">create_album</span><span class="p">(</span><span class="n">album_name</span><span class="p">)</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">album</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="PhotosAlbum"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotosAlbum">[docs]</a><span class="k">class</span> <span class="nc">PhotosAlbum</span><span class="p">:</span>
|
||||
<span class="sd">"""Add osxphotos.photoinfo.PhotoInfo objects to album"""</span>
|
||||
<span class="sd">"""Add osxphotos.photoinfo.PhotoInfo objects to album"""</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
|
||||
<span class="bp">self</span><span class="p">,</span>
|
||||
@@ -262,17 +296,17 @@
|
||||
<span class="n">split_folder</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">rich</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
|
||||
<span class="p">):</span>
|
||||
<span class="sd">"""Return a PhotosAlbum object, creating the album if necessary</span>
|
||||
<span class="sd">"""Return a PhotosAlbum object, creating the album if necessary</span>
|
||||
|
||||
<span class="sd"> Args:</span>
|
||||
<span class="sd"> name: Name of album</span>
|
||||
<span class="sd"> verbose: optional callable to print verbose output</span>
|
||||
<span class="sd"> split_folder: if set, split album name on value of split_folder to create folders if necessary,</span>
|
||||
<span class="sd"> e.g. if name = 'folder1/folder2/album' and split_folder='/',</span>
|
||||
<span class="sd"> then folders 'folder1' and 'folder2' will be created and album 'album' will be created in 'folder2';</span>
|
||||
<span class="sd"> if not set, album 'folder1/folder2/album' will be created</span>
|
||||
<span class="sd"> e.g. if name = 'folder1/folder2/album' and split_folder='/',</span>
|
||||
<span class="sd"> then folders 'folder1' and 'folder2' will be created and album 'album' will be created in 'folder2';</span>
|
||||
<span class="sd"> if not set, album 'folder1/folder2/album' will be created</span>
|
||||
<span class="sd"> rich: if True, use rich themes for verbose output</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">verbose</span> <span class="o">=</span> <span class="n">verbose</span> <span class="ow">or</span> <span class="n">noop</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">library</span> <span class="o">=</span> <span class="n">photoscript</span><span class="o">.</span><span class="n">PhotosLibrary</span><span class="p">()</span>
|
||||
|
||||
@@ -285,7 +319,7 @@
|
||||
<span class="n">photo_</span> <span class="o">=</span> <span class="n">photoscript</span><span class="o">.</span><span class="n">Photo</span><span class="p">(</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">album</span><span class="o">.</span><span class="n">add</span><span class="p">([</span><span class="n">photo_</span><span class="p">])</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">verbose</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Added </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_name</span><span class="p">(</span><span class="n">photo</span><span class="o">.</span><span class="n">original_filename</span><span class="p">)</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_uuid</span><span class="p">(</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span><span class="p">)</span><span class="si">}</span><span class="s2">) to album </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_album</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="sa">f</span><span class="s2">"Added </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_name</span><span class="p">(</span><span class="n">photo</span><span class="o">.</span><span class="n">original_filename</span><span class="p">)</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_uuid</span><span class="p">(</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span><span class="p">)</span><span class="si">}</span><span class="s2">) to album </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_album</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">add_list</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">photo_list</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">PhotoInfo</span><span class="p">]):</span>
|
||||
@@ -295,42 +329,42 @@
|
||||
<span class="n">photos</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">photoscript</span><span class="o">.</span><span class="n">Photo</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">uuid</span><span class="p">))</span>
|
||||
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">verbose</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Error creating Photo object for photo </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_uuid</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">uuid</span><span class="p">)</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="sa">f</span><span class="s2">"Error creating Photo object for photo </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_uuid</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">uuid</span><span class="p">)</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">photolist</span> <span class="ow">in</span> <span class="n">chunked</span><span class="p">(</span><span class="n">photos</span><span class="p">,</span> <span class="mi">10</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">album</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">photolist</span><span class="p">)</span>
|
||||
<span class="n">photo_len</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">photo_list</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">verbose</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Added </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_num</span><span class="p">(</span><span class="n">photo_len</span><span class="p">)</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">pluralize</span><span class="p">(</span><span class="n">photo_len</span><span class="p">,</span> <span class="s1">'photo'</span><span class="p">,</span> <span class="s1">'photos'</span><span class="p">)</span><span class="si">}</span><span class="s2"> to album </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_album</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="sa">f</span><span class="s2">"Added </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_num</span><span class="p">(</span><span class="n">photo_len</span><span class="p">)</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">pluralize</span><span class="p">(</span><span class="n">photo_len</span><span class="p">,</span> <span class="s1">'photo'</span><span class="p">,</span> <span class="s1">'photos'</span><span class="p">)</span><span class="si">}</span><span class="s2"> to album </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_album</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">photos</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">album</span><span class="o">.</span><span class="n">photos</span><span class="p">()</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_format_uuid</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">uuid</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
||||
<span class="sd">""" "Format uuid for verbose output"""</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"[uuid]</span><span class="si">{</span><span class="n">uuid</span><span class="si">}</span><span class="s2">[/uuid]"</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">rich</span> <span class="k">else</span> <span class="n">uuid</span>
|
||||
<span class="sd">""" "Format uuid for verbose output"""</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"[uuid]</span><span class="si">{</span><span class="n">uuid</span><span class="si">}</span><span class="s2">[/uuid]"</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">rich</span> <span class="k">else</span> <span class="n">uuid</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_format_album</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">album</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
||||
<span class="sd">""" "Format album name for verbose output"""</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"[filepath]</span><span class="si">{</span><span class="n">album</span><span class="si">}</span><span class="s2">[/filepath]"</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">rich</span> <span class="k">else</span> <span class="n">album</span>
|
||||
<span class="sd">""" "Format album name for verbose output"""</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"[filepath]</span><span class="si">{</span><span class="n">album</span><span class="si">}</span><span class="s2">[/filepath]"</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">rich</span> <span class="k">else</span> <span class="n">album</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_format_name</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
||||
<span class="sd">""" "Format name for verbose output"""</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"[filename]</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2">[/filename]"</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">rich</span> <span class="k">else</span> <span class="n">name</span>
|
||||
<span class="sd">""" "Format name for verbose output"""</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"[filename]</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2">[/filename]"</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">rich</span> <span class="k">else</span> <span class="n">name</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_format_num</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">num</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
||||
<span class="sd">""" "Format number for verbose output"""</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"[num]</span><span class="si">{</span><span class="n">num</span><span class="si">}</span><span class="s2">[/num]"</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">rich</span> <span class="k">else</span> <span class="nb">str</span><span class="p">(</span><span class="n">num</span><span class="p">)</span></div>
|
||||
<span class="sd">""" "Format number for verbose output"""</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"[num]</span><span class="si">{</span><span class="n">num</span><span class="si">}</span><span class="s2">[/num]"</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">rich</span> <span class="k">else</span> <span class="nb">str</span><span class="p">(</span><span class="n">num</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="PhotosAlbumPhotoScript"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotosAlbumPhotoScript">[docs]</a><span class="k">class</span> <span class="nc">PhotosAlbumPhotoScript</span><span class="p">(</span><span class="n">PhotosAlbum</span><span class="p">):</span>
|
||||
<span class="sd">"""Add photoscript.Photo objects to album"""</span>
|
||||
<span class="sd">"""Add photoscript.Photo objects to album"""</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">photo</span><span class="p">:</span> <span class="n">Photo</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">album</span><span class="o">.</span><span class="n">add</span><span class="p">([</span><span class="n">photo</span><span class="p">])</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">verbose</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Added </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_name</span><span class="p">(</span><span class="n">photo</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_uuid</span><span class="p">(</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span><span class="p">)</span><span class="si">}</span><span class="s2">) to album </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_album</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="sa">f</span><span class="s2">"Added </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_name</span><span class="p">(</span><span class="n">photo</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_uuid</span><span class="p">(</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span><span class="p">)</span><span class="si">}</span><span class="s2">) to album </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_album</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">add_list</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">photo_list</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Photo</span><span class="p">]):</span>
|
||||
@@ -338,7 +372,7 @@
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">album</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">photolist</span><span class="p">)</span>
|
||||
<span class="n">photo_len</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">photo_list</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">verbose</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Added </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_num</span><span class="p">(</span><span class="n">photo_len</span><span class="p">)</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">pluralize</span><span class="p">(</span><span class="n">photo_len</span><span class="p">,</span> <span class="s1">'photo'</span><span class="p">,</span> <span class="s1">'photos'</span><span class="p">)</span><span class="si">}</span><span class="s2"> to album </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_album</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="sa">f</span><span class="s2">"Added </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_num</span><span class="p">(</span><span class="n">photo_len</span><span class="p">)</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">pluralize</span><span class="p">(</span><span class="n">photo_len</span><span class="p">,</span> <span class="s1">'photo'</span><span class="p">,</span> <span class="s1">'photos'</span><span class="p">)</span><span class="si">}</span><span class="s2"> to album </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_format_album</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span></div>
|
||||
</pre></div>
|
||||
</article>
|
||||
@@ -377,7 +411,9 @@
|
||||
</div><script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
|
||||
<script src="../../_static/jquery.js"></script>
|
||||
<script src="../../_static/underscore.js"></script>
|
||||
<script src="../../_static/_sphinx_javascript_frameworks_compat.js"></script>
|
||||
<script src="../../_static/doctools.js"></script>
|
||||
<script src="../../_static/sphinx_highlight.js"></script>
|
||||
<script src="../../_static/scripts/furo.js"></script>
|
||||
<script src="../../_static/clipboard.min.js"></script>
|
||||
<script src="../../_static/copybutton.js"></script>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!doctype html>
|
||||
<html class="no-js">
|
||||
<html class="no-js" lang="en">
|
||||
<head><meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../../genindex.html" /><link rel="search" title="Search" href="../../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
|
||||
<title>osxphotos.photosdb._photosdb_process_comments - osxphotos 0.50.13 documentation</title>
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.photosdb._photosdb_process_comments - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/styles/furo.css?digest=68f4518137b9aefe99b631505a2064c3c42c9852" />
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/copybutton.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../../index.html"><div class="brand">osxphotos 0.50.13 documentation</div></a>
|
||||
<a href="../../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.50.13 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -179,7 +179,8 @@
|
||||
</svg>
|
||||
<span>Back to top</span>
|
||||
</a>
|
||||
<div class="content-icon-container"><div class="theme-toggle-container theme-toggle-content">
|
||||
<div class="content-icon-container">
|
||||
<div class="theme-toggle-container theme-toggle-content">
|
||||
<button class="theme-toggle">
|
||||
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
|
||||
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||||
@@ -194,23 +195,23 @@
|
||||
</div>
|
||||
<article role="main">
|
||||
<h1>Source code for osxphotos.photosdb._photosdb_process_comments</h1><div class="highlight"><pre>
|
||||
<span></span><span class="sd">""" PhotosDB method for processing comments and likes on shared photos.</span>
|
||||
<span class="sd"> Do not import this module directly """</span>
|
||||
<span></span><span class="sd">""" PhotosDB method for processing comments and likes on shared photos.</span>
|
||||
<span class="sd"> Do not import this module directly """</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">dataclasses</span>
|
||||
<span class="kn">import</span> <span class="nn">datetime</span>
|
||||
<span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">.._constants</span> <span class="kn">import</span> <span class="n">_DB_TABLE_NAMES</span><span class="p">,</span> <span class="n">_PHOTOS_4_VERSION</span><span class="p">,</span> <span class="n">TIME_DELTA</span>
|
||||
<span class="kn">from</span> <span class="nn">..utils</span> <span class="kn">import</span> <span class="n">normalize_unicode</span>
|
||||
<span class="kn">from</span> <span class="nn">..sqlite_utils</span> <span class="kn">import</span> <span class="n">sqlite_open_ro</span>
|
||||
<span class="kn">from</span> <span class="nn">..unicode</span> <span class="kn">import</span> <span class="n">normalize_unicode</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">_process_comments</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""load the comments and likes data from the database</span>
|
||||
<span class="sd">"""load the comments and likes data from the database</span>
|
||||
<span class="sd"> this is a PhotosDB method that should be imported in</span>
|
||||
<span class="sd"> the PhotosDB class definition in photosdb.py</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_db_hashed_person_id</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_db_comments_uuid</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db_version</span> <span class="o"><=</span> <span class="n">_PHOTOS_4_VERSION</span><span class="p">:</span>
|
||||
@@ -221,7 +222,7 @@
|
||||
|
||||
<div class="viewcode-block" id="CommentInfo"><a class="viewcode-back" href="../../../reference.html#osxphotos.CommentInfo">[docs]</a><span class="nd">@dataclass</span>
|
||||
<span class="k">class</span> <span class="nc">CommentInfo</span><span class="p">:</span>
|
||||
<span class="sd">"""Class for shared photo comments"""</span>
|
||||
<span class="sd">"""Class for shared photo comments"""</span>
|
||||
|
||||
<span class="n">datetime</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span>
|
||||
<span class="n">user</span><span class="p">:</span> <span class="nb">str</span>
|
||||
@@ -234,7 +235,7 @@
|
||||
|
||||
<div class="viewcode-block" id="LikeInfo"><a class="viewcode-back" href="../../../reference.html#osxphotos.LikeInfo">[docs]</a><span class="nd">@dataclass</span>
|
||||
<span class="k">class</span> <span class="nc">LikeInfo</span><span class="p">:</span>
|
||||
<span class="sd">"""Class for shared photo likes"""</span>
|
||||
<span class="sd">"""Class for shared photo likes"""</span>
|
||||
|
||||
<span class="n">datetime</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span>
|
||||
<span class="n">user</span><span class="p">:</span> <span class="nb">str</span>
|
||||
@@ -247,25 +248,25 @@
|
||||
<span class="c1"># The following methods do not get imported into PhotosDB</span>
|
||||
<span class="c1"># but will get called by _process_comments</span>
|
||||
<span class="k">def</span> <span class="nf">_process_comments_4</span><span class="p">(</span><span class="n">photosdb</span><span class="p">):</span>
|
||||
<span class="sd">"""process comments and likes info for Photos <= 4</span>
|
||||
<span class="sd"> photosdb: PhotosDB instance"""</span>
|
||||
<span class="sd">"""process comments and likes info for Photos <= 4</span>
|
||||
<span class="sd"> photosdb: PhotosDB instance"""</span>
|
||||
<span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Not implemented for database version </span><span class="si">{</span><span class="n">photosdb</span><span class="o">.</span><span class="n">_db_version</span><span class="si">}</span><span class="s2">."</span>
|
||||
<span class="sa">f</span><span class="s2">"Not implemented for database version </span><span class="si">{</span><span class="n">photosdb</span><span class="o">.</span><span class="n">_db_version</span><span class="si">}</span><span class="s2">."</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">_process_comments_5</span><span class="p">(</span><span class="n">photosdb</span><span class="p">):</span>
|
||||
<span class="sd">"""process comments and likes info for Photos >= 5</span>
|
||||
<span class="sd"> photosdb: PhotosDB instance"""</span>
|
||||
<span class="sd">"""process comments and likes info for Photos >= 5</span>
|
||||
<span class="sd"> photosdb: PhotosDB instance"""</span>
|
||||
|
||||
<span class="n">db</span> <span class="o">=</span> <span class="n">photosdb</span><span class="o">.</span><span class="n">_tmp_db</span>
|
||||
|
||||
<span class="n">asset_table</span> <span class="o">=</span> <span class="n">_DB_TABLE_NAMES</span><span class="p">[</span><span class="n">photosdb</span><span class="o">.</span><span class="n">_photos_ver</span><span class="p">][</span><span class="s2">"ASSET"</span><span class="p">]</span>
|
||||
<span class="n">asset_table</span> <span class="o">=</span> <span class="n">_DB_TABLE_NAMES</span><span class="p">[</span><span class="n">photosdb</span><span class="o">.</span><span class="n">_photos_ver</span><span class="p">][</span><span class="s2">"ASSET"</span><span class="p">]</span>
|
||||
|
||||
<span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="n">cursor</span><span class="p">)</span> <span class="o">=</span> <span class="n">sqlite_open_ro</span><span class="p">(</span><span class="n">db</span><span class="p">)</span>
|
||||
|
||||
<span class="n">results</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> SELECT DISTINCT</span>
|
||||
<span class="sd"> ZINVITEEHASHEDPERSONID AS HASHEDPERSONID,</span>
|
||||
<span class="sd"> ZINVITEEFIRSTNAME AS FIRSTNAME,</span>
|
||||
@@ -273,7 +274,7 @@
|
||||
<span class="sd"> ZINVITEEFULLNAME AS FULLNAME</span>
|
||||
<span class="sd"> FROM ZCLOUDSHAREDALBUMINVITATIONRECORD</span>
|
||||
<span class="sd"> WHERE HASHEDPERSONID IS NOT NULL</span>
|
||||
<span class="sd"> AND HASHEDPERSONID != ""</span>
|
||||
<span class="sd"> AND HASHEDPERSONID != ""</span>
|
||||
<span class="sd"> AND NOT (FIRSTNAME IS NULL AND LASTNAME IS NULL)</span>
|
||||
<span class="sd"> UNION</span>
|
||||
<span class="sd"> SELECT DISTINCT</span>
|
||||
@@ -283,9 +284,9 @@
|
||||
<span class="sd"> ZCLOUDOWNERFULLNAME AS FULLNAME</span>
|
||||
<span class="sd"> FROM ZGENERICALBUM</span>
|
||||
<span class="sd"> WHERE HASHEDPERSONID IS NOT NULL</span>
|
||||
<span class="sd"> AND HASHEDPERSONID != ""</span>
|
||||
<span class="sd"> AND HASHEDPERSONID != ""</span>
|
||||
<span class="sd"> AND NOT (FIRSTNAME IS NULL AND LASTNAME IS NULL)</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="c1"># order of results</span>
|
||||
@@ -298,35 +299,35 @@
|
||||
<span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">results</span><span class="o">.</span><span class="n">fetchall</span><span class="p">():</span>
|
||||
<span class="n">person_id</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="n">photosdb</span><span class="o">.</span><span class="n">_db_hashed_person_id</span><span class="p">[</span><span class="n">person_id</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
|
||||
<span class="s2">"first_name"</span><span class="p">:</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span>
|
||||
<span class="s2">"last_name"</span><span class="p">:</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span>
|
||||
<span class="s2">"full_name"</span><span class="p">:</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">3</span><span class="p">]),</span>
|
||||
<span class="s2">"first_name"</span><span class="p">:</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span>
|
||||
<span class="s2">"last_name"</span><span class="p">:</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span>
|
||||
<span class="s2">"full_name"</span><span class="p">:</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">3</span><span class="p">]),</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="n">results</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"""</span>
|
||||
<span class="sa">f</span><span class="s2">"""</span>
|
||||
<span class="s2"> SELECT </span>
|
||||
<span class="s2"> </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.ZUUID, -- UUID of the photo</span>
|
||||
<span class="s2"> ZCLOUDSHAREDCOMMENT.ZISLIKE, -- comment is actually a "like"</span>
|
||||
<span class="s2"> ZCLOUDSHAREDCOMMENT.ZISLIKE, -- comment is actually a "like"</span>
|
||||
<span class="s2"> ZCLOUDSHAREDCOMMENT.ZCOMMENTDATE, -- date of comment</span>
|
||||
<span class="s2"> ZCLOUDSHAREDCOMMENT.ZCOMMENTTEXT, -- text of comment</span>
|
||||
<span class="s2"> ZCLOUDSHAREDCOMMENT.ZCOMMENTERHASHEDPERSONID, -- hashed ID of person who made comment/like</span>
|
||||
<span class="s2"> ZCLOUDSHAREDCOMMENT.ZISMYCOMMENT -- is my (this user's) comment</span>
|
||||
<span class="s2"> ZCLOUDSHAREDCOMMENT.ZISMYCOMMENT -- is my (this user's) comment</span>
|
||||
<span class="s2"> FROM ZCLOUDSHAREDCOMMENT</span>
|
||||
<span class="s2"> JOIN </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2"> ON</span>
|
||||
<span class="s2"> </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.Z_PK = ZCLOUDSHAREDCOMMENT.ZCOMMENTEDASSET</span>
|
||||
<span class="s2"> OR</span>
|
||||
<span class="s2"> </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.Z_PK = ZCLOUDSHAREDCOMMENT.ZLIKEDASSET</span>
|
||||
<span class="s2"> """</span>
|
||||
<span class="s2"> """</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="c1"># order of results</span>
|
||||
<span class="c1"># 0: ZGENERICASSET.ZUUID, -- UUID of the photo</span>
|
||||
<span class="c1"># 1: ZCLOUDSHAREDCOMMENT.ZISLIKE, -- comment is actually a "like"</span>
|
||||
<span class="c1"># 1: ZCLOUDSHAREDCOMMENT.ZISLIKE, -- comment is actually a "like"</span>
|
||||
<span class="c1"># 2: ZCLOUDSHAREDCOMMENT.ZCOMMENTDATE, -- date of comment</span>
|
||||
<span class="c1"># 3: ZCLOUDSHAREDCOMMENT.ZCOMMENTTEXT, -- text of comment</span>
|
||||
<span class="c1"># 4: ZCLOUDSHAREDCOMMENT.ZCOMMENTERHASHEDPERSONID, -- hashed ID of person who made comment/like</span>
|
||||
<span class="c1"># 5: ZCLOUDSHAREDCOMMENT.ZISMYCOMMENT -- is my (this user's) comment</span>
|
||||
<span class="c1"># 5: ZCLOUDSHAREDCOMMENT.ZISMYCOMMENT -- is my (this user's) comment</span>
|
||||
|
||||
<span class="n">photosdb</span><span class="o">.</span><span class="n">_db_comments_uuid</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
<span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">results</span><span class="p">:</span>
|
||||
@@ -334,7 +335,7 @@
|
||||
<span class="n">is_like</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
|
||||
<span class="n">text</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">3</span><span class="p">])</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">user_name</span> <span class="o">=</span> <span class="n">photosdb</span><span class="o">.</span><span class="n">_db_hashed_person_id</span><span class="p">[</span><span class="n">row</span><span class="p">[</span><span class="mi">4</span><span class="p">]][</span><span class="s2">"full_name"</span><span class="p">]</span>
|
||||
<span class="n">user_name</span> <span class="o">=</span> <span class="n">photosdb</span><span class="o">.</span><span class="n">_db_hashed_person_id</span><span class="p">[</span><span class="n">row</span><span class="p">[</span><span class="mi">4</span><span class="p">]][</span><span class="s2">"full_name"</span><span class="p">]</span>
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="n">user_name</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
@@ -348,20 +349,20 @@
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">db_comments</span> <span class="o">=</span> <span class="n">photosdb</span><span class="o">.</span><span class="n">_db_comments_uuid</span><span class="p">[</span><span class="n">uuid</span><span class="p">]</span>
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="n">photosdb</span><span class="o">.</span><span class="n">_db_comments_uuid</span><span class="p">[</span><span class="n">uuid</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"likes"</span><span class="p">:</span> <span class="p">[],</span> <span class="s2">"comments"</span><span class="p">:</span> <span class="p">[]}</span>
|
||||
<span class="n">photosdb</span><span class="o">.</span><span class="n">_db_comments_uuid</span><span class="p">[</span><span class="n">uuid</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"likes"</span><span class="p">:</span> <span class="p">[],</span> <span class="s2">"comments"</span><span class="p">:</span> <span class="p">[]}</span>
|
||||
<span class="n">db_comments</span> <span class="o">=</span> <span class="n">photosdb</span><span class="o">.</span><span class="n">_db_comments_uuid</span><span class="p">[</span><span class="n">uuid</span><span class="p">]</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">is_like</span><span class="p">:</span>
|
||||
<span class="n">db_comments</span><span class="p">[</span><span class="s2">"likes"</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">LikeInfo</span><span class="p">(</span><span class="n">dt</span><span class="p">,</span> <span class="n">user_name</span><span class="p">,</span> <span class="n">ismine</span><span class="p">))</span>
|
||||
<span class="n">db_comments</span><span class="p">[</span><span class="s2">"likes"</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">LikeInfo</span><span class="p">(</span><span class="n">dt</span><span class="p">,</span> <span class="n">user_name</span><span class="p">,</span> <span class="n">ismine</span><span class="p">))</span>
|
||||
<span class="k">elif</span> <span class="n">text</span><span class="p">:</span>
|
||||
<span class="n">db_comments</span><span class="p">[</span><span class="s2">"comments"</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">CommentInfo</span><span class="p">(</span><span class="n">dt</span><span class="p">,</span> <span class="n">user_name</span><span class="p">,</span> <span class="n">ismine</span><span class="p">,</span> <span class="n">text</span><span class="p">))</span>
|
||||
<span class="n">db_comments</span><span class="p">[</span><span class="s2">"comments"</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">CommentInfo</span><span class="p">(</span><span class="n">dt</span><span class="p">,</span> <span class="n">user_name</span><span class="p">,</span> <span class="n">ismine</span><span class="p">,</span> <span class="n">text</span><span class="p">))</span>
|
||||
|
||||
<span class="c1"># sort results</span>
|
||||
<span class="k">for</span> <span class="n">uuid</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">photosdb</span><span class="o">.</span><span class="n">_db_comments_uuid</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
||||
<span class="k">if</span> <span class="n">photosdb</span><span class="o">.</span><span class="n">_db_comments_uuid</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"likes"</span><span class="p">]:</span>
|
||||
<span class="n">photosdb</span><span class="o">.</span><span class="n">_db_comments_uuid</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"likes"</span><span class="p">]</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">.</span><span class="n">datetime</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">photosdb</span><span class="o">.</span><span class="n">_db_comments_uuid</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"comments"</span><span class="p">]:</span>
|
||||
<span class="n">value</span><span class="p">[</span><span class="s2">"comments"</span><span class="p">]</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">.</span><span class="n">datetime</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">photosdb</span><span class="o">.</span><span class="n">_db_comments_uuid</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"likes"</span><span class="p">]:</span>
|
||||
<span class="n">photosdb</span><span class="o">.</span><span class="n">_db_comments_uuid</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"likes"</span><span class="p">]</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">.</span><span class="n">datetime</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">photosdb</span><span class="o">.</span><span class="n">_db_comments_uuid</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"comments"</span><span class="p">]:</span>
|
||||
<span class="n">value</span><span class="p">[</span><span class="s2">"comments"</span><span class="p">]</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">.</span><span class="n">datetime</span><span class="p">)</span>
|
||||
|
||||
<span class="n">conn</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
@@ -401,7 +402,9 @@
|
||||
</div><script data-url_root="../../../" id="documentation_options" src="../../../_static/documentation_options.js"></script>
|
||||
<script src="../../../_static/jquery.js"></script>
|
||||
<script src="../../../_static/underscore.js"></script>
|
||||
<script src="../../../_static/_sphinx_javascript_frameworks_compat.js"></script>
|
||||
<script src="../../../_static/doctools.js"></script>
|
||||
<script src="../../../_static/sphinx_highlight.js"></script>
|
||||
<script src="../../../_static/scripts/furo.js"></script>
|
||||
<script src="../../../_static/clipboard.min.js"></script>
|
||||
<script src="../../../_static/copybutton.js"></script>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../../genindex.html" /><link rel="search" title="Search" href="../../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.photosdb.photosdb - osxphotos 0.56.2 documentation</title>
|
||||
<title>osxphotos.photosdb.photosdb - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/copybutton.css" />
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../../index.html"><div class="brand">osxphotos 0.56.2 documentation</div></a>
|
||||
<a href="../../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.56.2 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -200,22 +200,24 @@
|
||||
<span class="sd">Processes a Photos.app library database to extract information about photos</span>
|
||||
<span class="sd">"""</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">annotations</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">logging</span>
|
||||
<span class="kn">import</span> <span class="nn">os</span>
|
||||
<span class="kn">import</span> <span class="nn">os.path</span>
|
||||
<span class="kn">import</span> <span class="nn">pathlib</span>
|
||||
<span class="kn">import</span> <span class="nn">platform</span>
|
||||
<span class="kn">import</span> <span class="nn">re</span>
|
||||
<span class="kn">import</span> <span class="nn">sqlite3</span>
|
||||
<span class="kn">import</span> <span class="nn">sys</span>
|
||||
<span class="kn">import</span> <span class="nn">tempfile</span>
|
||||
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">OrderedDict</span>
|
||||
<span class="kn">from</span> <span class="nn">collections.abc</span> <span class="kn">import</span> <span class="n">Iterable</span>
|
||||
<span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span><span class="p">,</span> <span class="n">timedelta</span><span class="p">,</span> <span class="n">timezone</span>
|
||||
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Optional</span>
|
||||
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Any</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">Optional</span>
|
||||
<span class="kn">from</span> <span class="nn">unicodedata</span> <span class="kn">import</span> <span class="n">normalize</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">bitmath</span>
|
||||
<span class="kn">import</span> <span class="nn">photoscript</span>
|
||||
<span class="kn">from</span> <span class="nn">rich</span> <span class="kn">import</span> <span class="nb">print</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">.._constants</span> <span class="kn">import</span> <span class="p">(</span>
|
||||
@@ -247,22 +249,22 @@
|
||||
<span class="kn">from</span> <span class="nn">.._version</span> <span class="kn">import</span> <span class="n">__version__</span>
|
||||
<span class="kn">from</span> <span class="nn">..albuminfo</span> <span class="kn">import</span> <span class="n">AlbumInfo</span><span class="p">,</span> <span class="n">FolderInfo</span><span class="p">,</span> <span class="n">ImportInfo</span><span class="p">,</span> <span class="n">ProjectInfo</span>
|
||||
<span class="kn">from</span> <span class="nn">..datetime_utils</span> <span class="kn">import</span> <span class="n">datetime_has_tz</span><span class="p">,</span> <span class="n">datetime_naive_to_local</span>
|
||||
<span class="kn">from</span> <span class="nn">..debug</span> <span class="kn">import</span> <span class="n">is_debug</span>
|
||||
<span class="kn">from</span> <span class="nn">..fileutil</span> <span class="kn">import</span> <span class="n">FileUtil</span>
|
||||
<span class="kn">from</span> <span class="nn">..personinfo</span> <span class="kn">import</span> <span class="n">PersonInfo</span>
|
||||
<span class="kn">from</span> <span class="nn">..photoinfo</span> <span class="kn">import</span> <span class="n">PhotoInfo</span>
|
||||
<span class="kn">from</span> <span class="nn">..phototemplate</span> <span class="kn">import</span> <span class="n">RenderOptions</span>
|
||||
<span class="kn">from</span> <span class="nn">..platform</span> <span class="kn">import</span> <span class="n">get_macos_version</span><span class="p">,</span> <span class="n">is_macos</span>
|
||||
<span class="kn">from</span> <span class="nn">..queryoptions</span> <span class="kn">import</span> <span class="n">QueryOptions</span>
|
||||
<span class="kn">from</span> <span class="nn">..rich_utils</span> <span class="kn">import</span> <span class="n">add_rich_markup_tag</span>
|
||||
<span class="kn">from</span> <span class="nn">..sqlite_utils</span> <span class="kn">import</span> <span class="n">sqlite_db_is_locked</span><span class="p">,</span> <span class="n">sqlite_open_ro</span>
|
||||
<span class="kn">from</span> <span class="nn">..utils</span> <span class="kn">import</span> <span class="p">(</span>
|
||||
<span class="n">_check_file_exists</span><span class="p">,</span>
|
||||
<span class="n">_get_os_version</span><span class="p">,</span>
|
||||
<span class="n">get_last_library_path</span><span class="p">,</span>
|
||||
<span class="n">noop</span><span class="p">,</span>
|
||||
<span class="n">normalize_unicode</span><span class="p">,</span>
|
||||
<span class="p">)</span>
|
||||
<span class="kn">from</span> <span class="nn">.photosdb_utils</span> <span class="kn">import</span> <span class="n">get_db_model_version</span><span class="p">,</span> <span class="n">get_db_version</span>
|
||||
<span class="kn">from</span> <span class="nn">..unicode</span> <span class="kn">import</span> <span class="n">normalize_unicode</span>
|
||||
<span class="kn">from</span> <span class="nn">..utils</span> <span class="kn">import</span> <span class="n">_check_file_exists</span><span class="p">,</span> <span class="n">get_last_library_path</span><span class="p">,</span> <span class="n">noop</span>
|
||||
<span class="kn">from</span> <span class="nn">.photosdb_utils</span> <span class="kn">import</span> <span class="n">get_photos_version_from_model</span><span class="p">,</span> <span class="n">get_db_version</span><span class="p">,</span> <span class="n">get_model_version</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">is_macos</span><span class="p">:</span>
|
||||
<span class="kn">import</span> <span class="nn">photoscript</span>
|
||||
|
||||
<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s2">"osxphotos"</span><span class="p">)</span>
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"PhotosDB"</span><span class="p">]</span>
|
||||
|
||||
@@ -286,6 +288,7 @@
|
||||
<span class="n">labels_normalized</span><span class="p">,</span>
|
||||
<span class="n">labels_normalized_as_dict</span><span class="p">,</span>
|
||||
<span class="p">)</span>
|
||||
<span class="kn">from</span> <span class="nn">._photosdb_process_syndicationinfo</span> <span class="kn">import</span> <span class="n">_process_syndicationinfo</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
|
||||
<span class="bp">self</span><span class="p">,</span>
|
||||
@@ -311,8 +314,8 @@
|
||||
|
||||
<span class="c1"># Check OS version</span>
|
||||
<span class="n">system</span> <span class="o">=</span> <span class="n">platform</span><span class="o">.</span><span class="n">system</span><span class="p">()</span>
|
||||
<span class="p">(</span><span class="n">ver</span><span class="p">,</span> <span class="n">major</span><span class="p">,</span> <span class="n">_</span><span class="p">)</span> <span class="o">=</span> <span class="n">_get_os_version</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="n">system</span> <span class="o">!=</span> <span class="s2">"Darwin"</span> <span class="ow">or</span> <span class="p">((</span><span class="n">ver</span><span class="p">,</span> <span class="n">major</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">_TESTED_OS_VERSIONS</span><span class="p">):</span>
|
||||
<span class="p">(</span><span class="n">ver</span><span class="p">,</span> <span class="n">major</span><span class="p">,</span> <span class="n">_</span><span class="p">)</span> <span class="o">=</span> <span class="n">get_macos_version</span><span class="p">()</span> <span class="k">if</span> <span class="n">is_macos</span> <span class="k">else</span> <span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">system</span> <span class="o">==</span> <span class="s2">"Darwin"</span> <span class="ow">and</span> <span class="p">((</span><span class="n">ver</span><span class="p">,</span> <span class="n">major</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">_TESTED_OS_VERSIONS</span><span class="p">):</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"WARNING: This module has only been tested with macOS versions "</span>
|
||||
<span class="sa">f</span><span class="s2">"[</span><span class="si">{</span><span class="s1">', '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">v</span><span class="si">}</span><span class="s1">.</span><span class="si">{</span><span class="n">m</span><span class="si">}</span><span class="s1">'</span> <span class="k">for</span> <span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="ow">in</span> <span class="n">_TESTED_OS_VERSIONS</span><span class="p">)</span><span class="si">}</span><span class="s2">]: "</span>
|
||||
@@ -477,8 +480,14 @@
|
||||
<span class="c1"># key is Z_PK of ZMOMENT table and values are the moment info</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_db_moment_pk</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">is_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"dbfile = </span><span class="si">{</span><span class="n">dbfile</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="c1"># Dict to hold data on imports for Photos <= 4</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_db_import_group</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
|
||||
<span class="c1"># Dict to hold syndication info for Photos >= 8</span>
|
||||
<span class="c1"># key is UUID and value is dict of syndication info</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_db_syndication_uuid</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"dbfile = </span><span class="si">{</span><span class="n">dbfile</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">dbfile</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="n">dbfile</span> <span class="o">=</span> <span class="n">get_last_library_path</span><span class="p">()</span>
|
||||
@@ -494,8 +503,7 @@
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">_check_file_exists</span><span class="p">(</span><span class="n">dbfile</span><span class="p">):</span>
|
||||
<span class="k">raise</span> <span class="ne">FileNotFoundError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"dbfile </span><span class="si">{</span><span class="n">dbfile</span><span class="si">}</span><span class="s2"> does not exist"</span><span class="p">,</span> <span class="n">dbfile</span><span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">is_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"dbfile = </span><span class="si">{</span><span class="n">dbfile</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"dbfile = </span><span class="si">{</span><span class="n">dbfile</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># init database names</span>
|
||||
<span class="c1"># _tmp_db is the file that will processed by _process_database4/5</span>
|
||||
@@ -515,13 +523,22 @@
|
||||
<span class="c1"># photoanalysisd sometimes maintains this lock even after Photos is closed</span>
|
||||
<span class="c1"># In those cases, make a temp copy of the file for sqlite3 to read</span>
|
||||
<span class="k">if</span> <span class="n">sqlite_db_is_locked</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfile</span><span class="p">):</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Database locked, creating temporary copy."</span><span class="p">)</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Database locked, creating temporary copy."</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_tmp_db</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_copy_db_file</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfile</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># _db_version is set from photos.db</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_db_version</span> <span class="o">=</span> <span class="n">get_db_version</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_tmp_db</span><span class="p">)</span>
|
||||
<span class="c1"># _photos_version is set from Photos.sqlite which only exists for Photos 5+</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_photos_ver</span> <span class="o">=</span> <span class="mi">4</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db_version</span> <span class="o">==</span> <span class="mi">4</span> <span class="k">else</span> <span class="mi">5</span>
|
||||
<span class="n">db_ver_int</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_db_version</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">db_ver_int</span> <span class="o"><</span> <span class="mi">3000</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_photos_ver</span> <span class="o">=</span> <span class="mi">2</span>
|
||||
<span class="k">elif</span> <span class="n">db_ver_int</span> <span class="o"><</span> <span class="mi">4000</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_photos_ver</span> <span class="o">=</span> <span class="mi">3</span>
|
||||
<span class="k">elif</span> <span class="n">db_ver_int</span> <span class="o"><</span> <span class="mi">5000</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_photos_ver</span> <span class="o">=</span> <span class="mi">4</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_photos_ver</span> <span class="o">=</span> <span class="mi">5</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_model_ver</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1"># only set for Photos 5+</span>
|
||||
|
||||
<span class="c1"># If Photos >= 5, actual data isn't in photos.db but in Photos.sqlite</span>
|
||||
<span class="k">if</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_db_version</span><span class="p">)</span> <span class="o">></span> <span class="nb">int</span><span class="p">(</span><span class="n">_PHOTOS_4_VERSION</span><span class="p">):</span>
|
||||
@@ -529,20 +546,19 @@
|
||||
<span class="n">dbfile</span> <span class="o">=</span> <span class="n">dbpath</span> <span class="o">/</span> <span class="s2">"Photos.sqlite"</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">_check_file_exists</span><span class="p">(</span><span class="n">dbfile</span><span class="p">):</span>
|
||||
<span class="k">raise</span> <span class="ne">FileNotFoundError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"dbfile </span><span class="si">{</span><span class="n">dbfile</span><span class="si">}</span><span class="s2"> does not exist"</span><span class="p">,</span> <span class="n">dbfile</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbfile_actual</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_tmp_db</span> <span class="o">=</span> <span class="n">dbfile</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Processing database </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_filepath</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfile_actual</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="c1"># if database is exclusively locked, make a copy of it and use the copy</span>
|
||||
<span class="k">if</span> <span class="n">sqlite_db_is_locked</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfile_actual</span><span class="p">):</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Database locked, creating temporary copy."</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_tmp_db</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_copy_db_file</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfile_actual</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbfile_actual</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_tmp_db</span> <span class="o">=</span> <span class="n">dbfile</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Processing database </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_filepath</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfile_actual</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="c1"># if database is exclusively locked, make a copy of it and use the copy</span>
|
||||
<span class="k">if</span> <span class="n">sqlite_db_is_locked</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfile_actual</span><span class="p">):</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Database locked, creating temporary copy."</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_tmp_db</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_copy_db_file</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfile_actual</span><span class="p">)</span>
|
||||
<span class="c1"># set the photos version to actual value based on Photos.sqlite</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_photos_ver</span> <span class="o">=</span> <span class="n">get_db_model_version</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_tmp_db</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_photos_ver</span> <span class="o">=</span> <span class="n">get_photos_version_from_model</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_tmp_db</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_model_ver</span> <span class="o">=</span> <span class="n">get_model_version</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_tmp_db</span><span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">is_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"_dbfile = </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfile</span><span class="si">}</span><span class="s2">, _dbfile_actual = </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfile_actual</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"_dbfile = </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfile</span><span class="si">}</span><span class="s2">, _dbfile_actual = </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbfile_actual</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="n">library_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">dbfile</span><span class="p">))</span>
|
||||
<span class="p">(</span><span class="n">library_path</span><span class="p">,</span> <span class="n">_</span><span class="p">)</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">library_path</span><span class="p">)</span> <span class="c1"># drop /database from path</span>
|
||||
@@ -554,8 +570,7 @@
|
||||
<span class="n">masters_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">library_path</span><span class="p">,</span> <span class="s2">"originals"</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_masters_path</span> <span class="o">=</span> <span class="n">masters_path</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">is_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"library = </span><span class="si">{</span><span class="n">library_path</span><span class="si">}</span><span class="s2">, masters = </span><span class="si">{</span><span class="n">masters_path</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"library = </span><span class="si">{</span><span class="n">library_path</span><span class="si">}</span><span class="s2">, masters = </span><span class="si">{</span><span class="n">masters_path</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_db_version</span><span class="p">)</span> <span class="o"><=</span> <span class="nb">int</span><span class="p">(</span><span class="n">_PHOTOS_4_VERSION</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_process_database4</span><span class="p">()</span>
|
||||
@@ -703,7 +718,8 @@
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">album_info_shared</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""return list of AlbumInfo objects for each shared album in the photos database</span>
|
||||
<span class="sd"> only valid for Photos 5; on Photos <= 4, prints warning and returns empty list"""</span>
|
||||
<span class="sd"> only valid for Photos 5; on Photos <= 4, prints warning and returns empty list</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="c1"># if _dbalbum_details[key]["cloudownerhashedpersonid"] is not None, then it's a shared album</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_album_info_shared</span>
|
||||
@@ -730,7 +746,8 @@
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">albums_shared</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""return list of shared albums found in photos database</span>
|
||||
<span class="sd"> only valid for Photos 5; on Photos <= 4, prints warning and returns empty list"""</span>
|
||||
<span class="sd"> only valid for Photos 5; on Photos <= 4, prints warning and returns empty list</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="c1"># Could be more than one album with same name</span>
|
||||
<span class="c1"># Right now, they are treated as same album and photos are combined from albums with same name</span>
|
||||
@@ -782,6 +799,11 @@
|
||||
<span class="sd">"""returns path to the Photos library PhotosDB was initialized with"""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_library_path</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">photos_version</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""returns version of Photos app that created the library"""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photos_ver</span>
|
||||
|
||||
<div class="viewcode-block" id="PhotosDB.get_db_connection"><a class="viewcode-back" href="../../../reference.html#osxphotos.PhotosDB.get_db_connection">[docs]</a> <span class="k">def</span> <span class="nf">get_db_connection</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Get connection to the working copy of the Photos database</span>
|
||||
|
||||
@@ -810,38 +832,10 @@
|
||||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Error copying</span><span class="si">{</span><span class="n">fname</span><span class="si">}</span><span class="s2"> to </span><span class="si">{</span><span class="n">dest_path</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span>
|
||||
<span class="k">raise</span> <span class="ne">Exception</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">is_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">dest_path</span><span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">dest_path</span><span class="p">)</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">dest_path</span>
|
||||
|
||||
<span class="c1"># NOTE: This method seems to cause problems with applescript</span>
|
||||
<span class="c1"># Bummer...would'be been nice to avoid copying the DB</span>
|
||||
<span class="c1"># def _link_db_file(self, fname):</span>
|
||||
<span class="c1"># """ links the sqlite database file to a temp file """</span>
|
||||
<span class="c1"># """ returns the name of the temp file """</span>
|
||||
<span class="c1"># """ If sqlite shared memory and write-ahead log files exist, those are copied too """</span>
|
||||
<span class="c1"># # required because python's sqlite3 implementation can't read a locked file</span>
|
||||
<span class="c1"># # _, suffix = os.path.splitext(fname)</span>
|
||||
<span class="c1"># dest_name = dest_path = ""</span>
|
||||
<span class="c1"># try:</span>
|
||||
<span class="c1"># dest_name = pathlib.Path(fname).name</span>
|
||||
<span class="c1"># dest_path = os.path.join(self._tempdir_name, dest_name)</span>
|
||||
<span class="c1"># FileUtil.hardlink(fname, dest_path)</span>
|
||||
<span class="c1"># # link write-ahead log and shared memory files (-wal and -shm) files if they exist</span>
|
||||
<span class="c1"># if os.path.exists(f"{fname}-wal"):</span>
|
||||
<span class="c1"># FileUtil.hardlink(f"{fname}-wal", f"{dest_path}-wal")</span>
|
||||
<span class="c1"># if os.path.exists(f"{fname}-shm"):</span>
|
||||
<span class="c1"># FileUtil.hardlink(f"{fname}-shm", f"{dest_path}-shm")</span>
|
||||
<span class="c1"># except:</span>
|
||||
<span class="c1"># print("Error linking " + fname + " to " + dest_path, file=sys.stderr)</span>
|
||||
<span class="c1"># raise Exception</span>
|
||||
|
||||
<span class="c1"># if is_debug():</span>
|
||||
<span class="c1"># logging.debug(dest_path)</span>
|
||||
|
||||
<span class="c1"># return dest_path</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_process_database4</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""process the Photos database to extract info</span>
|
||||
<span class="sd"> works on Photos version <= 4.0"""</span>
|
||||
@@ -890,6 +884,8 @@
|
||||
<span class="s2">"displayname"</span><span class="p">:</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">person</span><span class="p">[</span><span class="mi">4</span><span class="p">]),</span>
|
||||
<span class="s2">"photo_uuid"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"keyface_uuid"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"type"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="c1"># Photos 5+</span>
|
||||
<span class="s2">"manualorder"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="c1"># Photos 5+</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_fullname</span><span class="p">[</span><span class="n">fullname</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pk</span><span class="p">)</span>
|
||||
@@ -921,7 +917,7 @@
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_pk</span><span class="p">[</span><span class="n">pk</span><span class="p">][</span><span class="s2">"photo_uuid"</span><span class="p">]</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_pk</span><span class="p">[</span><span class="n">pk</span><span class="p">][</span><span class="s2">"keyface_uuid"</span><span class="p">]</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unexpected KeyError _dbpersons_pk[</span><span class="si">{</span><span class="n">pk</span><span class="si">}</span><span class="s2">]"</span><span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unexpected KeyError _dbpersons_pk[</span><span class="si">{</span><span class="n">pk</span><span class="si">}</span><span class="s2">]"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># get information on detected faces</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Processing detected faces in photos."</span><span class="p">)</span>
|
||||
@@ -1019,10 +1015,10 @@
|
||||
<span class="s2">"cloudlibrarystate"</span><span class="p">:</span> <span class="n">album</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span>
|
||||
<span class="s2">"cloudidentifier"</span><span class="p">:</span> <span class="n">album</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span>
|
||||
<span class="s2">"intrash"</span><span class="p">:</span> <span class="kc">False</span> <span class="k">if</span> <span class="n">album</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span> <span class="k">else</span> <span class="kc">True</span><span class="p">,</span>
|
||||
<span class="s2">"cloudlocalstate"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="c1"># Photos 5</span>
|
||||
<span class="s2">"cloudownerfirstname"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="c1"># Photos 5</span>
|
||||
<span class="s2">"cloudownderlastname"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="c1"># Photos 5</span>
|
||||
<span class="s2">"cloudownerhashedpersonid"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="c1"># Photos 5</span>
|
||||
<span class="s2">"cloudlocalstate"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="c1"># Photos 5+</span>
|
||||
<span class="s2">"cloudownerfirstname"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="c1"># Photos 5+</span>
|
||||
<span class="s2">"cloudownderlastname"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="c1"># Photos 5+</span>
|
||||
<span class="s2">"cloudownerhashedpersonid"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="c1"># Photos 5+</span>
|
||||
<span class="s2">"folderUuid"</span><span class="p">:</span> <span class="n">album</span><span class="p">[</span><span class="mi">5</span><span class="p">],</span>
|
||||
<span class="s2">"albumType"</span><span class="p">:</span> <span class="n">album</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span>
|
||||
<span class="s2">"albumSubclass"</span><span class="p">:</span> <span class="n">album</span><span class="p">[</span><span class="mi">7</span><span class="p">],</span>
|
||||
@@ -1253,9 +1249,8 @@
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"lastmodifieddate"</span><span class="p">]</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">fromtimestamp</span><span class="p">(</span>
|
||||
<span class="n">row</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">+</span> <span class="n">TIME_DELTA</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"lastmodifieddate"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span>
|
||||
<span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">):</span>
|
||||
<span class="c1"># sometimes the date is invalid or null</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"lastmodifieddate"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"imageTimeZoneOffsetSeconds"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span>
|
||||
@@ -1267,8 +1262,8 @@
|
||||
<span class="n">delta</span> <span class="o">=</span> <span class="n">timedelta</span><span class="p">(</span><span class="n">seconds</span><span class="o">=</span><span class="n">seconds</span><span class="p">)</span>
|
||||
<span class="n">tz</span> <span class="o">=</span> <span class="n">timezone</span><span class="p">(</span><span class="n">delta</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"imageDate"</span><span class="p">]</span> <span class="o">=</span> <span class="n">imagedate</span><span class="o">.</span><span class="n">astimezone</span><span class="p">(</span><span class="n">tz</span><span class="o">=</span><span class="n">tz</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="c1"># sometimes imageDate is invalid so use 1 Jan 1970 in UTC as image date</span>
|
||||
<span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">):</span>
|
||||
<span class="c1"># sometimes imageDate is invalid so use 1 Jan 1970 as image date</span>
|
||||
<span class="n">imagedate</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">(</span><span class="mi">1970</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||||
<span class="n">tz</span> <span class="o">=</span> <span class="n">timezone</span><span class="p">(</span><span class="n">timedelta</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"imageDate"</span><span class="p">]</span> <span class="o">=</span> <span class="n">imagedate</span><span class="o">.</span><span class="n">astimezone</span><span class="p">(</span><span class="n">tz</span><span class="o">=</span><span class="n">tz</span><span class="p">)</span>
|
||||
@@ -1298,8 +1293,7 @@
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"type"</span><span class="p">]</span> <span class="o">=</span> <span class="n">_MOVIE_TYPE</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="c1"># unknown</span>
|
||||
<span class="k">if</span> <span class="n">is_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"WARNING: </span><span class="si">{</span><span class="n">uuid</span><span class="si">}</span><span class="s2"> found unknown type </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">21</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"WARNING: </span><span class="si">{</span><span class="n">uuid</span><span class="si">}</span><span class="s2"> found unknown type </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">21</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"type"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"UTI"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">22</span><span class="p">]</span>
|
||||
@@ -1364,12 +1358,13 @@
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"momentID"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">28</span><span class="p">]</span>
|
||||
|
||||
<span class="c1"># Init cloud details that will be filled in later if cloud asset</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"cloudAssetGUID"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Photos 5</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"cloudLocalState"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Photos 5</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"cloudAssetGUID"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Photos 5+</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"cloudLocalState"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Photos 5+</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"cloudLibraryState"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"cloudStatus"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"cloudAvailable"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"incloud"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"cloudMasterGUID"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Photos 5+</span>
|
||||
|
||||
<span class="c1"># associated RAW image info</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"has_raw"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span> <span class="k">if</span> <span class="n">row</span><span class="p">[</span><span class="mi">25</span><span class="p">]</span> <span class="o">==</span> <span class="mi">7</span> <span class="k">else</span> <span class="kc">False</span>
|
||||
@@ -1439,6 +1434,9 @@
|
||||
<span class="c1"># photos 5+ only, for shared photos</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"cloudownerhashedpersonid"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
<span class="c1"># photos 7+ only, shared moments</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"moment_share"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
<span class="c1"># compute signatures for finding possible duplicates</span>
|
||||
<span class="n">signature</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_duplicate_signature</span><span class="p">(</span><span class="n">uuid</span><span class="p">)</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
@@ -1532,21 +1530,19 @@
|
||||
<span class="k">if</span> <span class="n">resource_type</span> <span class="o">==</span> <span class="mi">4</span><span class="p">:</span>
|
||||
<span class="c1"># photo</span>
|
||||
<span class="k">if</span> <span class="s2">"edit_resource_id_photo"</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">]:</span>
|
||||
<span class="k">if</span> <span class="n">is_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"WARNING: found more than one edit_resource_id_photo for "</span>
|
||||
<span class="sa">f</span><span class="s2">"UUID </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s2">,adjustmentUUID </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s2">, modelID </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"WARNING: found more than one edit_resource_id_photo for "</span>
|
||||
<span class="sa">f</span><span class="s2">"UUID </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s2">,adjustmentUUID </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s2">, modelID </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"edit_resource_id_photo"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"UTI_edited_photo"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span>
|
||||
<span class="k">elif</span> <span class="n">resource_type</span> <span class="o">==</span> <span class="mi">8</span><span class="p">:</span>
|
||||
<span class="c1"># video</span>
|
||||
<span class="k">if</span> <span class="s2">"edit_resource_id_video"</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">]:</span>
|
||||
<span class="k">if</span> <span class="n">is_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"WARNING: found more than one edit_resource_id_video for "</span>
|
||||
<span class="sa">f</span><span class="s2">"UUID </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s2">,adjustmentUUID </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s2">, modelID </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"WARNING: found more than one edit_resource_id_video for "</span>
|
||||
<span class="sa">f</span><span class="s2">"UUID </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s2">,adjustmentUUID </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s2">, modelID </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"edit_resource_id_video"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"UTI_edited_video"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span>
|
||||
|
||||
@@ -1835,8 +1831,7 @@
|
||||
<span class="sd"> but it works so don't touch it.</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">is_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"_process_database5"</span><span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"_process_database5"</span><span class="p">)</span>
|
||||
<span class="n">verbose</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_verbose</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Processing database."</span><span class="p">)</span>
|
||||
<span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span> <span class="o">=</span> <span class="n">sqlite_open_ro</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_tmp_db</span><span class="p">)</span>
|
||||
@@ -1859,8 +1854,7 @@
|
||||
<span class="n">hdr_type_column</span> <span class="o">=</span> <span class="n">_DB_TABLE_NAMES</span><span class="p">[</span><span class="n">photos_ver</span><span class="p">][</span><span class="s2">"HDR_TYPE"</span><span class="p">]</span>
|
||||
|
||||
<span class="c1"># Look for all combinations of persons and pictures</span>
|
||||
<span class="k">if</span> <span class="n">is_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Getting information about persons"</span><span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Getting information about persons"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># get info to associate persons with photos</span>
|
||||
<span class="c1"># then get detected faces in each photo and link to persons</span>
|
||||
@@ -1872,7 +1866,9 @@
|
||||
<span class="sd"> ZPERSON.ZFULLNAME,</span>
|
||||
<span class="sd"> ZPERSON.ZFACECOUNT,</span>
|
||||
<span class="sd"> ZPERSON.ZKEYFACE,</span>
|
||||
<span class="sd"> ZPERSON.ZDISPLAYNAME</span>
|
||||
<span class="sd"> ZPERSON.ZDISPLAYNAME,</span>
|
||||
<span class="sd"> ZPERSON.ZTYPE,</span>
|
||||
<span class="sd"> ZPERSON.ZMANUALORDER</span>
|
||||
<span class="sd"> FROM ZPERSON</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">)</span>
|
||||
@@ -1883,6 +1879,8 @@
|
||||
<span class="c1"># 3 ZPERSON.ZFACECOUNT,</span>
|
||||
<span class="c1"># 4 ZPERSON.ZKEYFACE,</span>
|
||||
<span class="c1"># 5 ZPERSON.ZDISPLAYNAME</span>
|
||||
<span class="c1"># 6 ZPERSON.ZTYPE, # ZTYPE = 1 == favorite, 0 == not favorite</span>
|
||||
<span class="c1"># 7 ZPERSON.ZMANUALORDER # favorites are sorted by ZMANUALORDER</span>
|
||||
|
||||
<span class="k">for</span> <span class="n">person</span> <span class="ow">in</span> <span class="n">c</span><span class="p">:</span>
|
||||
<span class="n">pk</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
@@ -1900,6 +1898,8 @@
|
||||
<span class="s2">"displayname"</span><span class="p">:</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">person</span><span class="p">[</span><span class="mi">5</span><span class="p">]),</span>
|
||||
<span class="s2">"photo_uuid"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"keyface_uuid"</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"type"</span><span class="p">:</span> <span class="n">person</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span>
|
||||
<span class="s2">"manualorder"</span><span class="p">:</span> <span class="n">person</span><span class="p">[</span><span class="mi">7</span><span class="p">],</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_fullname</span><span class="p">[</span><span class="n">fullname</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pk</span><span class="p">)</span>
|
||||
@@ -1908,6 +1908,7 @@
|
||||
|
||||
<span class="c1"># get info on keyface -- some photos have null keyface so can't do a single query</span>
|
||||
<span class="c1"># (at least not with my SQL skills)</span>
|
||||
<span class="n">asset_fk</span> <span class="o">=</span> <span class="n">_DB_TABLE_NAMES</span><span class="p">[</span><span class="n">photos_ver</span><span class="p">][</span><span class="s2">"DETECTED_FACE_ASSET_FK"</span><span class="p">]</span>
|
||||
<span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">""" SELECT</span>
|
||||
<span class="s2"> ZPERSON.Z_PK,</span>
|
||||
@@ -1916,7 +1917,7 @@
|
||||
<span class="s2"> ZDETECTEDFACE.ZUUID</span>
|
||||
<span class="s2"> FROM ZPERSON, ZDETECTEDFACE, </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2"></span>
|
||||
<span class="s2"> WHERE ZDETECTEDFACE.Z_PK = ZPERSON.ZKEYFACE AND</span>
|
||||
<span class="s2"> ZDETECTEDFACE.ZASSET = </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.Z_PK</span>
|
||||
<span class="s2"> </span><span class="si">{</span><span class="n">asset_fk</span><span class="si">}</span><span class="s2"> = </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.Z_PK</span>
|
||||
<span class="s2"> """</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
@@ -1931,17 +1932,18 @@
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_pk</span><span class="p">[</span><span class="n">pk</span><span class="p">][</span><span class="s2">"photo_uuid"</span><span class="p">]</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbpersons_pk</span><span class="p">[</span><span class="n">pk</span><span class="p">][</span><span class="s2">"keyface_uuid"</span><span class="p">]</span> <span class="o">=</span> <span class="n">person</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unexpected KeyError _dbpersons_pk[</span><span class="si">{</span><span class="n">pk</span><span class="si">}</span><span class="s2">]"</span><span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unexpected KeyError _dbpersons_pk[</span><span class="si">{</span><span class="n">pk</span><span class="si">}</span><span class="s2">]"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># get information on detected faces</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Processing detected faces in photos."</span><span class="p">)</span>
|
||||
<span class="n">person_fk</span> <span class="o">=</span> <span class="n">_DB_TABLE_NAMES</span><span class="p">[</span><span class="n">photos_ver</span><span class="p">][</span><span class="s2">"DETECTED_FACE_PERSON_FK"</span><span class="p">]</span>
|
||||
<span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">""" SELECT</span>
|
||||
<span class="s2"> ZPERSON.Z_PK,</span>
|
||||
<span class="s2"> </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.ZUUID</span>
|
||||
<span class="s2"> FROM ZPERSON, ZDETECTEDFACE, </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2"></span>
|
||||
<span class="s2"> WHERE ZDETECTEDFACE.ZPERSON = ZPERSON.Z_PK AND</span>
|
||||
<span class="s2"> ZDETECTEDFACE.ZASSET = </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.Z_PK</span>
|
||||
<span class="s2"> WHERE </span><span class="si">{</span><span class="n">person_fk</span><span class="si">}</span><span class="s2"> = ZPERSON.Z_PK AND</span>
|
||||
<span class="s2"> </span><span class="si">{</span><span class="n">asset_fk</span><span class="si">}</span><span class="s2"> = </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.Z_PK</span>
|
||||
<span class="s2"> """</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
@@ -2149,7 +2151,8 @@
|
||||
<span class="s2"> </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.ZSAVEDASSETTYPE,</span>
|
||||
<span class="s2"> </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.ZADDEDDATE,</span>
|
||||
<span class="s2"> </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.Z_PK,</span>
|
||||
<span class="s2"> </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.ZCLOUDOWNERHASHEDPERSONID</span>
|
||||
<span class="s2"> </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.ZCLOUDOWNERHASHEDPERSONID,</span>
|
||||
<span class="s2"> </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.ZMOMENTSHARE</span>
|
||||
<span class="s2"> FROM </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2"> </span>
|
||||
<span class="s2"> JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.Z_PK </span>
|
||||
<span class="s2"> ORDER BY </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.ZUUID """</span>
|
||||
@@ -2200,6 +2203,7 @@
|
||||
<span class="c1"># 41 ZGENERICASSET.ZADDEDDATE -- date item added to the library</span>
|
||||
<span class="c1"># 42 ZGENERICASSET.Z_PK -- primary key</span>
|
||||
<span class="c1"># 43 ZGENERICASSET.ZCLOUDOWNERHASHEDPERSONID -- used to look up owner name (for shared photos)</span>
|
||||
<span class="c1"># 44 ZASSET.ZMOMENTSHARE -- FK for ZSHARE (shared moments, Photos 5+; in Photos 7+ these are in the scopes/momentshared folder)</span>
|
||||
|
||||
<span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">c</span><span class="p">:</span>
|
||||
<span class="n">uuid</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
@@ -2228,8 +2232,8 @@
|
||||
<span class="n">delta</span> <span class="o">=</span> <span class="n">timedelta</span><span class="p">(</span><span class="n">seconds</span><span class="o">=</span><span class="n">seconds</span><span class="p">)</span>
|
||||
<span class="n">tz</span> <span class="o">=</span> <span class="n">timezone</span><span class="p">(</span><span class="n">delta</span><span class="p">)</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"imageDate"</span><span class="p">]</span> <span class="o">=</span> <span class="n">imagedate</span><span class="o">.</span><span class="n">astimezone</span><span class="p">(</span><span class="n">tz</span><span class="o">=</span><span class="n">tz</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="c1"># sometimes imageDate is invalid so use 1 Jan 1970 in UTC as image date</span>
|
||||
<span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">):</span>
|
||||
<span class="c1"># sometimes imageDate is invalid or null so use 1 Jan 1970 in UTC as image date (#1014)</span>
|
||||
<span class="n">imagedate</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">(</span><span class="mi">1970</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||||
<span class="n">tz</span> <span class="o">=</span> <span class="n">timezone</span><span class="p">(</span><span class="n">timedelta</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"imageDate"</span><span class="p">]</span> <span class="o">=</span> <span class="n">imagedate</span><span class="o">.</span><span class="n">astimezone</span><span class="p">(</span><span class="n">tz</span><span class="o">=</span><span class="n">tz</span><span class="p">)</span>
|
||||
@@ -2269,8 +2273,7 @@
|
||||
<span class="k">elif</span> <span class="n">row</span><span class="p">[</span><span class="mi">17</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"type"</span><span class="p">]</span> <span class="o">=</span> <span class="n">_MOVIE_TYPE</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="n">is_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"WARNING: </span><span class="si">{</span><span class="n">uuid</span><span class="si">}</span><span class="s2"> found unknown type </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">17</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"WARNING: </span><span class="si">{</span><span class="n">uuid</span><span class="si">}</span><span class="s2"> found unknown type </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">17</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"type"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"UTI"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">18</span><span class="p">]</span>
|
||||
@@ -2331,6 +2334,7 @@
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"cloudLibraryState"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Photos 4</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"cloudStatus"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Photos 4</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"cloudAvailable"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Photos 4</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"cloudMasterGUID"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
<span class="c1"># reverse geolocation info</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"reverse_geolocation"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">25</span><span class="p">]</span>
|
||||
@@ -2387,6 +2391,8 @@
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"pk"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">42</span><span class="p">]</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"cloudownerhashedpersonid"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">43</span><span class="p">]</span>
|
||||
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"moment_share"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">44</span><span class="p">]</span>
|
||||
|
||||
<span class="c1"># initialize import session info which will be filled in later</span>
|
||||
<span class="c1"># not every photo has an import session so initialize all records now</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"import_session"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
@@ -2457,7 +2463,7 @@
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"fok_import_session"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"import_uuid"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"No info record for uuid </span><span class="si">{</span><span class="n">uuid</span><span class="si">}</span><span class="s2"> for import session"</span><span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"No info record for uuid </span><span class="si">{</span><span class="n">uuid</span><span class="si">}</span><span class="s2"> for import session"</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># Get extended description</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Processing additional photo details."</span><span class="p">)</span>
|
||||
@@ -2474,10 +2480,9 @@
|
||||
<span class="k">if</span> <span class="n">uuid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"extendedDescription"</span><span class="p">]</span> <span class="o">=</span> <span class="n">normalize_unicode</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="n">is_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"WARNING: found description </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s2"> but no photo for </span><span class="si">{</span><span class="n">uuid</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"WARNING: found description </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s2"> but no photo for </span><span class="si">{</span><span class="n">uuid</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="c1"># get information about adjusted/edited photos</span>
|
||||
<span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
|
||||
@@ -2493,10 +2498,9 @@
|
||||
<span class="k">if</span> <span class="n">uuid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"adjustmentFormatID"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="n">is_debug</span><span class="p">():</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"WARNING: found adjustmentformatidentifier </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="si">}</span><span class="s2"> but no photo for uuid </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"WARNING: found adjustmentformatidentifier </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="si">}</span><span class="s2"> but no photo for uuid </span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="c1"># Find missing photos</span>
|
||||
<span class="c1"># TODO: this code is very kludgy and I had to make lots of assumptions</span>
|
||||
@@ -2579,7 +2583,8 @@
|
||||
<span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">""" SELECT</span>
|
||||
<span class="s2"> </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.ZUUID,</span>
|
||||
<span class="s2"> ZCLOUDMASTER.ZCLOUDLOCALSTATE</span>
|
||||
<span class="s2"> ZCLOUDMASTER.ZCLOUDLOCALSTATE,</span>
|
||||
<span class="s2"> ZCLOUDMASTER.ZCLOUDMASTERGUID</span>
|
||||
<span class="s2"> FROM ZCLOUDMASTER, </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2"></span>
|
||||
<span class="s2"> WHERE </span><span class="si">{</span><span class="n">asset_table</span><span class="si">}</span><span class="s2">.ZMASTER = ZCLOUDMASTER.Z_PK """</span>
|
||||
<span class="p">)</span>
|
||||
@@ -2588,6 +2593,7 @@
|
||||
<span class="k">if</span> <span class="n">uuid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"cloudLocalState"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"incloud"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span> <span class="k">if</span> <span class="n">row</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">3</span> <span class="k">else</span> <span class="kc">False</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">][</span><span class="s2">"cloudMasterGUID"</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
|
||||
<span class="c1"># get information about associted RAW images</span>
|
||||
<span class="c1"># RAW images have ZDATASTORESUBTYPE = 17</span>
|
||||
@@ -2719,6 +2725,10 @@
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Processing moments."</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_process_moments</span><span class="p">()</span>
|
||||
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photos_version</span> <span class="o">>=</span> <span class="mi">7</span><span class="p">:</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Processing syndication info."</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_process_syndicationinfo</span><span class="p">()</span>
|
||||
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Done processing details from Photos library."</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_process_moments</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
@@ -2811,8 +2821,8 @@
|
||||
<span class="c1"># save raw time stamp valu</span>
|
||||
<span class="n">moment_info</span><span class="p">[</span><span class="n">date_name</span> <span class="o">+</span> <span class="s2">"_timestamp"</span><span class="p">]</span> <span class="o">=</span> <span class="n">moment_info</span><span class="p">[</span><span class="n">date_name</span><span class="p">]</span>
|
||||
<span class="n">moment_info</span><span class="p">[</span><span class="n">date_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">moment_date</span><span class="o">.</span><span class="n">astimezone</span><span class="p">(</span><span class="n">tz</span><span class="o">=</span><span class="n">tz</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="c1"># sometimes imageDate is invalid so use 1 Jan 1970 in UTC as image date</span>
|
||||
<span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">):</span>
|
||||
<span class="c1"># sometimes imageDate is invalid or null so use 1 Jan 1970 in UTC as image date</span>
|
||||
<span class="n">moment_date</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">(</span><span class="mi">1970</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||||
<span class="n">tz</span> <span class="o">=</span> <span class="n">timezone</span><span class="p">(</span><span class="n">timedelta</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
|
||||
<span class="n">moment_info</span><span class="p">[</span><span class="n">date_name</span> <span class="o">+</span> <span class="s2">"_timestamp"</span><span class="p">]</span> <span class="o">=</span> <span class="n">date_stamp</span>
|
||||
@@ -2870,7 +2880,7 @@
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">folders</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_folders</span><span class="p">[</span><span class="n">album_uuid</span><span class="p">]</span>
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Caught _dbalbum_folders KeyError for album: </span><span class="si">{</span><span class="n">album_uuid</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Caught _dbalbum_folders KeyError for album: </span><span class="si">{</span><span class="n">album_uuid</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="p">[]</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_recurse_folder_hierarchy</span><span class="p">(</span><span class="n">folders</span><span class="p">,</span> <span class="n">hierarchy</span><span class="o">=</span><span class="p">[]):</span>
|
||||
@@ -2907,7 +2917,7 @@
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">folders</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbalbum_folders</span><span class="p">[</span><span class="n">album_uuid</span><span class="p">]</span>
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Caught _dbalbum_folders KeyError for album: </span><span class="si">{</span><span class="n">album_uuid</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Caught _dbalbum_folders KeyError for album: </span><span class="si">{</span><span class="n">album_uuid</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="p">[]</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_recurse_folder_hierarchy</span><span class="p">(</span><span class="n">folders</span><span class="p">,</span> <span class="n">hierarchy</span><span class="o">=</span><span class="p">[]):</span>
|
||||
@@ -3260,7 +3270,6 @@
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="kc">None</span></div>
|
||||
|
||||
<span class="c1"># TODO: add to docs and test</span>
|
||||
<div class="viewcode-block" id="PhotosDB.photos_by_uuid"><a class="viewcode-back" href="../../../reference.html#osxphotos.PhotosDB.photos_by_uuid">[docs]</a> <span class="k">def</span> <span class="nf">photos_by_uuid</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">uuids</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns a list of photos with UUID in uuids.</span>
|
||||
<span class="sd"> Does not generate error if invalid or missing UUID passed.</span>
|
||||
@@ -3273,14 +3282,11 @@
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> list of PhotoInfo instance for photo with UUID matching uuid or [] if no match</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">photos</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="n">uuid</span> <span class="ow">in</span> <span class="n">uuids</span><span class="p">:</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">photos</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">PhotoInfo</span><span class="p">(</span><span class="n">db</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span> <span class="n">uuid</span><span class="o">=</span><span class="n">uuid</span><span class="p">,</span> <span class="n">info</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">]))</span>
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="c1"># ignore missing/invlaid UUID</span>
|
||||
<span class="k">pass</span>
|
||||
<span class="k">return</span> <span class="n">photos</span></div>
|
||||
<span class="k">return</span> <span class="p">[</span>
|
||||
<span class="n">PhotoInfo</span><span class="p">(</span><span class="n">db</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span> <span class="n">uuid</span><span class="o">=</span><span class="n">uuid</span><span class="p">,</span> <span class="n">info</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span><span class="p">[</span><span class="n">uuid</span><span class="p">])</span>
|
||||
<span class="k">for</span> <span class="n">uuid</span> <span class="ow">in</span> <span class="n">uuids</span>
|
||||
<span class="k">if</span> <span class="n">uuid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dbphotos</span>
|
||||
<span class="p">]</span></div>
|
||||
|
||||
<div class="viewcode-block" id="PhotosDB.query"><a class="viewcode-back" href="../../../reference.html#osxphotos.PhotosDB.query">[docs]</a> <span class="k">def</span> <span class="nf">query</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">options</span><span class="p">:</span> <span class="n">QueryOptions</span><span class="p">)</span> <span class="o">-></span> <span class="n">List</span><span class="p">[</span><span class="n">PhotoInfo</span><span class="p">]:</span>
|
||||
<span class="sd">"""Run a query against PhotosDB to extract the photos based on user supplied options</span>
|
||||
@@ -3438,6 +3444,8 @@
|
||||
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">edited</span><span class="p">:</span>
|
||||
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">hasadjustments</span><span class="p">]</span>
|
||||
<span class="k">elif</span> <span class="n">options</span><span class="o">.</span><span class="n">not_edited</span><span class="p">:</span>
|
||||
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">p</span><span class="o">.</span><span class="n">hasadjustments</span><span class="p">]</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">external_edit</span><span class="p">:</span>
|
||||
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">external_edit</span><span class="p">]</span>
|
||||
@@ -3720,6 +3728,21 @@
|
||||
<span class="n">added_after</span> <span class="o">=</span> <span class="n">datetime_naive_to_local</span><span class="p">(</span><span class="n">added_after</span><span class="p">)</span>
|
||||
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">date_added</span> <span class="ow">and</span> <span class="n">p</span><span class="o">.</span><span class="n">date_added</span> <span class="o">></span> <span class="n">added_after</span><span class="p">]</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">syndicated</span><span class="p">:</span>
|
||||
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">syndicated</span><span class="p">]</span>
|
||||
<span class="k">elif</span> <span class="n">options</span><span class="o">.</span><span class="n">not_syndicated</span><span class="p">:</span>
|
||||
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">p</span><span class="o">.</span><span class="n">syndicated</span><span class="p">]</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">saved_to_library</span><span class="p">:</span>
|
||||
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">syndicated</span> <span class="ow">and</span> <span class="n">p</span><span class="o">.</span><span class="n">saved_to_library</span><span class="p">]</span>
|
||||
<span class="k">elif</span> <span class="n">options</span><span class="o">.</span><span class="n">not_saved_to_library</span><span class="p">:</span>
|
||||
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">syndicated</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">p</span><span class="o">.</span><span class="n">saved_to_library</span><span class="p">]</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">shared_moment</span><span class="p">:</span>
|
||||
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">shared_moment</span><span class="p">]</span>
|
||||
<span class="k">elif</span> <span class="n">options</span><span class="o">.</span><span class="n">not_shared_moment</span><span class="p">:</span>
|
||||
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">p</span><span class="o">.</span><span class="n">shared_moment</span><span class="p">]</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">function</span><span class="p">:</span>
|
||||
<span class="k">for</span> <span class="n">function</span> <span class="ow">in</span> <span class="n">options</span><span class="o">.</span><span class="n">function</span><span class="p">:</span>
|
||||
<span class="n">photos</span> <span class="o">=</span> <span class="n">function</span><span class="p">[</span><span class="mi">0</span><span class="p">](</span><span class="n">photos</span><span class="p">)</span>
|
||||
@@ -3748,10 +3771,11 @@
|
||||
|
||||
<span class="k">return</span> <span class="n">photos</span></div>
|
||||
|
||||
<div class="viewcode-block" id="PhotosDB.execute"><a class="viewcode-back" href="../../../reference.html#osxphotos.PhotosDB.execute">[docs]</a> <span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sql</span><span class="p">):</span>
|
||||
<div class="viewcode-block" id="PhotosDB.execute"><a class="viewcode-back" href="../../../reference.html#osxphotos.PhotosDB.execute">[docs]</a> <span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sql</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">params</span><span class="p">:</span> <span class="n">Any</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-></span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">Cursor</span><span class="p">:</span>
|
||||
<span class="sd">"""Execute sql statement and return cursor"""</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_db_connection</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_db_connection</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db_connection</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">sql</span><span class="p">)</span></div>
|
||||
<span class="n">params</span> <span class="o">=</span> <span class="n">params</span> <span class="ow">or</span> <span class="p">()</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_db_connection</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">params</span><span class="p">)</span></div>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_duplicate_signature</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">uuid</span><span class="p">):</span>
|
||||
<span class="sd">"""Compute a signature for finding possible duplicates"""</span>
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<!-- Generated with Sphinx 5.3.0 and Furo 2022.12.07 -->
|
||||
<title>osxphotos.phototemplate - osxphotos 0.55.4 documentation</title>
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.phototemplate - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=91d0f0d1c444bdcb17a68e833c7a53903343c195" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.55.4 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,10 +146,10 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.55.4 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
<input type="hidden" name="check_keywords" value="yes">
|
||||
<input type="hidden" name="area" value="default">
|
||||
</form>
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -211,12 +211,13 @@
|
||||
|
||||
<span class="kn">from</span> <span class="nn">textx</span> <span class="kn">import</span> <span class="n">TextXSyntaxError</span><span class="p">,</span> <span class="n">metamodel_from_file</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">osxphotos.template_counter</span> <span class="k">as</span> <span class="nn">counter</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">._constants</span> <span class="kn">import</span> <span class="n">_UNKNOWN_PERSON</span><span class="p">,</span> <span class="n">TEXT_DETECTION_CONFIDENCE_THRESHOLD</span>
|
||||
<span class="kn">from</span> <span class="nn">._version</span> <span class="kn">import</span> <span class="n">__version__</span>
|
||||
<span class="kn">from</span> <span class="nn">.datetime_formatter</span> <span class="kn">import</span> <span class="n">DateTimeFormatter</span>
|
||||
<span class="kn">from</span> <span class="nn">.exiftool</span> <span class="kn">import</span> <span class="n">ExifToolCaching</span>
|
||||
<span class="kn">from</span> <span class="nn">.path_utils</span> <span class="kn">import</span> <span class="n">sanitize_dirname</span><span class="p">,</span> <span class="n">sanitize_filename</span><span class="p">,</span> <span class="n">sanitize_pathpart</span>
|
||||
<span class="kn">from</span> <span class="nn">.text_detection</span> <span class="kn">import</span> <span class="n">detect_text</span>
|
||||
<span class="kn">from</span> <span class="nn">.utils</span> <span class="kn">import</span> <span class="n">expand_and_validate_filepath</span><span class="p">,</span> <span class="n">load_function</span><span class="p">,</span> <span class="n">uuid_to_shortuuid</span>
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span>
|
||||
@@ -348,6 +349,24 @@
|
||||
<span class="o">+</span> <span class="s2">"May be formatted using a python string format code. "</span>
|
||||
<span class="o">+</span> <span class="s2">"For example, to format as a 5-digit integer and pad with zeros, use '</span><span class="si">{id:05d}</span><span class="s2">' which results in "</span>
|
||||
<span class="o">+</span> <span class="s2">"00001, 00002, 00003...etc. "</span><span class="p">,</span>
|
||||
<span class="s2">"</span><span class="si">{counter}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"A sequential counter, starting at 0, that increments each time it is evaluated."</span>
|
||||
<span class="o">+</span> <span class="s2">"To start counting at a value other than 0, append append '(starting_value)' to the field name."</span>
|
||||
<span class="o">+</span> <span class="s2">"For example, to start counting at 1 instead of 0: '{counter(1)}'."</span>
|
||||
<span class="o">+</span> <span class="s2">"May be formatted using a python string format code."</span>
|
||||
<span class="o">+</span> <span class="s2">"For example, to format as a 5-digit integer and pad with zeros, use '{counter:05d(1)}'"</span>
|
||||
<span class="o">+</span> <span class="s2">"which results in 00001, 00002, 00003...etc."</span>
|
||||
<span class="o">+</span> <span class="s2">"You may also specify a stop value which causes the counter to reset to the starting value"</span>
|
||||
<span class="o">+</span> <span class="s2">"when the stop value is reached and a step size which causes the counter to increment by"</span>
|
||||
<span class="o">+</span> <span class="s2">"the specified value instead of 1. Use the format '{counter(start,stop,step)}' where start,"</span>
|
||||
<span class="o">+</span> <span class="s2">"stop, and step are integers. For example, to count from 1 to 10 by 2, use '{counter(1,11,2)}'."</span>
|
||||
<span class="o">+</span> <span class="s2">"Note that the counter stops counting when the stop value is reached and does not return the"</span>
|
||||
<span class="o">+</span> <span class="s2">"stop value. Start, stop, and step are optional and may be omitted. For example, to count"</span>
|
||||
<span class="o">+</span> <span class="s2">"from 0 by 2s, use '{counter(,,2)}'."</span>
|
||||
<span class="o">+</span> <span class="s2">"You may create an arbitrary number of counters by appending a unique name to the field name"</span>
|
||||
<span class="o">+</span> <span class="s2">"preceded by a period: '</span><span class="si">{counter.a}</span><span class="s2">', '</span><span class="si">{counter.b}</span><span class="s2">', etc. Each counter will have its own state"</span>
|
||||
<span class="o">+</span> <span class="s2">"and will start at 0 and increment by 1 unless otherwise specified."</span>
|
||||
<span class="o">+</span> <span class="s2">" Note: </span><span class="si">{counter}</span><span class="s2"> is not suitable for use with 'export' and '--update' "</span>
|
||||
<span class="o">+</span> <span class="s2">"as the counter associated with a photo may change between export sessions. See also </span><span class="si">{id}</span><span class="s2">."</span><span class="p">,</span>
|
||||
<span class="s2">"</span><span class="si">{album_seq}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"An integer, starting at 0, indicating the photo's index (sequence) in the containing album. "</span>
|
||||
<span class="o">+</span> <span class="s2">"Only valid when used in a '--filename' template and only when '</span><span class="si">{album}</span><span class="s2">' or '</span><span class="si">{folder_album}</span><span class="s2">' is used in the '--directory' template. "</span>
|
||||
<span class="o">+</span> <span class="s1">'For example </span><span class="se">\'</span><span class="s1">--directory "</span><span class="si">{folder_album}</span><span class="s1">" --filename "</span><span class="si">{album_seq}</span><span class="s1">_</span><span class="si">{original_name}</span><span class="s1">"</span><span class="se">\'</span><span class="s1">. '</span>
|
||||
@@ -462,6 +481,8 @@
|
||||
<span class="o">+</span> <span class="s2">"e.g. join(): ['a', 'b', 'c'] => 'abc'."</span><span class="p">,</span>
|
||||
<span class="s2">"append(x)"</span><span class="p">:</span> <span class="s2">"Append x to list of values, e.g. append(d): ['a', 'b', 'c'] => ['a', 'b', 'c', 'd']."</span><span class="p">,</span>
|
||||
<span class="s2">"prepend(x)"</span><span class="p">:</span> <span class="s2">"Prepend x to list of values, e.g. prepend(d): ['a', 'b', 'c'] => ['d', 'a', 'b', 'c']."</span><span class="p">,</span>
|
||||
<span class="s2">"appends(x)"</span><span class="p">:</span> <span class="s2">"Append s[tring] Append x to each value of list of values, e.g. appends(d): ['a', 'b', 'c'] => ['ad', 'bd', 'cd']."</span><span class="p">,</span>
|
||||
<span class="s2">"prepends(x)"</span><span class="p">:</span> <span class="s2">"Prepend s[tring] x to each value of list of values, e.g. prepends(d): ['a', 'b', 'c'] => ['da', 'db', 'dc']."</span><span class="p">,</span>
|
||||
<span class="s2">"remove(x)"</span><span class="p">:</span> <span class="s2">"Remove x from list of values, e.g. remove(b): ['a', 'b', 'c'] => ['a', 'c']."</span><span class="p">,</span>
|
||||
<span class="s2">"slice(start:stop:step)"</span><span class="p">:</span> <span class="s2">"Slice list using same semantics as Python's list slicing, "</span>
|
||||
<span class="o">+</span> <span class="s2">"e.g. slice(1:3): ['a', 'b', 'c', 'd'] => ['b', 'c']; slice(1:4:2): ['a', 'b', 'c', 'd'] => ['b', 'd']; "</span>
|
||||
@@ -498,6 +519,9 @@
|
||||
<span class="n">INPLACE_DEFAULT</span> <span class="o">=</span> <span class="s2">","</span>
|
||||
<span class="n">PATH_SEP_DEFAULT</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">sep</span>
|
||||
|
||||
<span class="c1"># globals for tracking {seq} substitutions</span>
|
||||
<span class="n">_global_seq_count</span> <span class="o">=</span> <span class="mi">0</span>
|
||||
|
||||
<span class="n">PUNCTUATION</span> <span class="o">=</span> <span class="p">{</span>
|
||||
<span class="s2">"comma"</span><span class="p">:</span> <span class="s2">","</span><span class="p">,</span>
|
||||
<span class="s2">"semicolon"</span><span class="p">:</span> <span class="s2">";"</span><span class="p">,</span>
|
||||
@@ -717,6 +741,8 @@
|
||||
<span class="c1"># process field arguments</span>
|
||||
<span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">fieldarg</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="n">field_arg</span> <span class="o">=</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">fieldarg</span><span class="o">.</span><span class="n">value</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">field_arg</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
<span class="c1"># process delim</span>
|
||||
<span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">delim</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||||
@@ -1116,6 +1142,8 @@
|
||||
<span class="n">start_id</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">field_arg</span><span class="p">)</span> <span class="k">if</span> <span class="n">field_arg</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="mi">0</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">+</span> <span class="n">start_id</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="n">format_str_value</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">subfield</span><span class="p">)</span>
|
||||
<span class="k">elif</span> <span class="n">field</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"counter"</span><span class="p">):</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="n">counter</span><span class="o">.</span><span class="n">get_counter_value</span><span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="n">subfield</span><span class="p">,</span> <span class="n">field_arg</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="c1"># if here, didn't get a match</span>
|
||||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unhandled template value: </span><span class="si">{</span><span class="n">field</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
@@ -1179,15 +1207,17 @@
|
||||
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unknown filter: </span><span class="si">{</span><span class="n">filter_</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">filter_</span> <span class="ow">in</span> <span class="p">[</span>
|
||||
<span class="s2">"split"</span><span class="p">,</span>
|
||||
<span class="s2">"chop"</span><span class="p">,</span>
|
||||
<span class="s2">"chomp"</span><span class="p">,</span>
|
||||
<span class="s2">"append"</span><span class="p">,</span>
|
||||
<span class="s2">"appends"</span><span class="p">,</span>
|
||||
<span class="s2">"chomp"</span><span class="p">,</span>
|
||||
<span class="s2">"chop"</span><span class="p">,</span>
|
||||
<span class="s2">"filter"</span><span class="p">,</span>
|
||||
<span class="s2">"prepend"</span><span class="p">,</span>
|
||||
<span class="s2">"prepends"</span><span class="p">,</span>
|
||||
<span class="s2">"remove"</span><span class="p">,</span>
|
||||
<span class="s2">"slice"</span><span class="p">,</span>
|
||||
<span class="s2">"split"</span><span class="p">,</span>
|
||||
<span class="s2">"sslice"</span><span class="p">,</span>
|
||||
<span class="s2">"filter"</span><span class="p">,</span>
|
||||
<span class="p">]</span> <span class="ow">and</span> <span class="p">(</span><span class="n">args</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">)):</span>
|
||||
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">filter_</span><span class="si">}</span><span class="s2"> requires arguments"</span><span class="p">)</span>
|
||||
|
||||
@@ -1204,15 +1234,13 @@
|
||||
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"braces"</span><span class="p">:</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"{"</span> <span class="o">+</span> <span class="n">v</span> <span class="o">+</span> <span class="s2">"}"</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
||||
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"parens"</span><span class="p">:</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"("</span> <span class="o">+</span> <span class="n">v</span> <span class="o">+</span> <span class="s2">")"</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="sa">f</span><span class="s2">"(</span><span class="si">{</span><span class="n">v</span><span class="si">}</span><span class="s2">)"</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
||||
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"brackets"</span><span class="p">:</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"["</span> <span class="o">+</span> <span class="n">v</span> <span class="o">+</span> <span class="s2">"]"</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="sa">f</span><span class="s2">"[</span><span class="si">{</span><span class="n">v</span><span class="si">}</span><span class="s2">]"</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
||||
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"shell_quote"</span><span class="p">:</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">shlex</span><span class="o">.</span><span class="n">quote</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
||||
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"split"</span><span class="p">:</span>
|
||||
<span class="c1"># split on delimiter</span>
|
||||
<span class="n">delim</span> <span class="o">=</span> <span class="n">args</span>
|
||||
<span class="k">if</span> <span class="n">delim</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="n">delim</span> <span class="o">:=</span> <span class="n">args</span><span class="p">:</span>
|
||||
<span class="n">new_values</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
|
||||
<span class="n">new_values</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">v</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">delim</span><span class="p">))</span>
|
||||
@@ -1223,15 +1251,15 @@
|
||||
<span class="c1"># chop off characters from the end</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">chop</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Invalid value for chop: </span><span class="si">{</span><span class="n">args</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Invalid value for chop: </span><span class="si">{</span><span class="n">args</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="p">[:</span><span class="o">-</span><span class="n">chop</span><span class="p">]</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span> <span class="k">if</span> <span class="n">chop</span> <span class="k">else</span> <span class="n">values</span>
|
||||
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"chomp"</span><span class="p">:</span>
|
||||
<span class="c1"># chop off characters from the beginning</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">chomp</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Invalid value for chomp: </span><span class="si">{</span><span class="n">args</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Invalid value for chomp: </span><span class="si">{</span><span class="n">args</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="p">[</span><span class="n">chomp</span><span class="p">:]</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span> <span class="k">if</span> <span class="n">chomp</span> <span class="k">else</span> <span class="n">values</span>
|
||||
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"autosplit"</span><span class="p">:</span>
|
||||
<span class="c1"># try to split keyword strings automatically</span>
|
||||
@@ -1266,6 +1294,12 @@
|
||||
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"prepend"</span><span class="p">:</span>
|
||||
<span class="c1"># prepend value to list</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">args</span><span class="p">]</span> <span class="o">+</span> <span class="n">values</span>
|
||||
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"appends"</span><span class="p">:</span>
|
||||
<span class="c1"># append value to each item in list</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">v</span><span class="si">}{</span><span class="n">args</span><span class="si">}</span><span class="s2">"</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
||||
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"prepends"</span><span class="p">:</span>
|
||||
<span class="c1"># prepend value to each item in list</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">args</span><span class="si">}{</span><span class="n">v</span><span class="si">}</span><span class="s2">"</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
||||
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"remove"</span><span class="p">:</span>
|
||||
<span class="c1"># remove value from list</span>
|
||||
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span> <span class="k">if</span> <span class="n">v</span> <span class="o">!=</span> <span class="n">args</span><span class="p">]</span>
|
||||
@@ -1315,7 +1349,7 @@
|
||||
<span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"comparison operators may only be used with values that can be converted to numbers: </span><span class="si">{</span><span class="n">vals</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">conditional_value</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="sa">f</span><span class="s2">"comparison operators may only be used with values that can be converted to numbers: </span><span class="si">{</span><span class="n">value</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">conditional_value</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
||||
|
||||
<span class="n">predicate_is_true</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
@@ -1514,7 +1548,7 @@
|
||||
<span class="n">subfield</span> <span class="o">=</span> <span class="n">subfield</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="n">subfield</span> <span class="ow">in</span> <span class="n">exifdict</span><span class="p">:</span>
|
||||
<span class="n">values</span> <span class="o">=</span> <span class="n">exifdict</span><span class="p">[</span><span class="n">subfield</span><span class="p">]</span>
|
||||
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">values</span><span class="p">]</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="nb">list</span><span class="p">)</span> <span class="k">else</span> <span class="n">values</span>
|
||||
<span class="n">values</span> <span class="o">=</span> <span class="n">values</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="nb">list</span><span class="p">)</span> <span class="k">else</span> <span class="p">[</span><span class="n">values</span><span class="p">]</span>
|
||||
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
||||
|
||||
<span class="c1"># sanitize directory names if needed</span>
|
||||
@@ -1844,7 +1878,7 @@
|
||||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unhandled template value: </span><span class="si">{</span><span class="n">field</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">get_place_value</span><span class="p">(</span><span class="n">photo</span><span class="p">:</span> <span class="s2">"PhotoInfo"</span><span class="p">,</span> <span class="n">field</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
|
||||
<span class="k">def</span> <span class="nf">get_place_value</span><span class="p">(</span><span class="n">photo</span><span class="p">:</span> <span class="s2">"PhotoInfo"</span><span class="p">,</span> <span class="n">field</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span> <span class="c1"># noqa: F821</span>
|
||||
<span class="sd">"""Get the value of a 'place' field by attribute</span>
|
||||
|
||||
<span class="sd"> Args:</span>
|
||||
@@ -1912,7 +1946,9 @@
|
||||
|
||||
</div>
|
||||
<div class="right-details">
|
||||
|
||||
<div class="icons">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!doctype html>
|
||||
<html class="no-js">
|
||||
<html class="no-js" lang="en">
|
||||
<head><meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
|
||||
<title>osxphotos.placeinfo - osxphotos 0.51.7 documentation</title>
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.placeinfo - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=68f4518137b9aefe99b631505a2064c3c42c9852" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.51.7 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.51.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -179,7 +179,8 @@
|
||||
</svg>
|
||||
<span>Back to top</span>
|
||||
</a>
|
||||
<div class="content-icon-container"><div class="theme-toggle-container theme-toggle-content">
|
||||
<div class="content-icon-container">
|
||||
<div class="theme-toggle-container theme-toggle-content">
|
||||
<button class="theme-toggle">
|
||||
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
|
||||
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||||
@@ -194,44 +195,46 @@
|
||||
</div>
|
||||
<article role="main">
|
||||
<h1>Source code for osxphotos.placeinfo</h1><div class="highlight"><pre>
|
||||
<span></span><span class="sd">""" </span>
|
||||
<span></span><span class="sd">""" </span>
|
||||
<span class="sd"> PlaceInfo class</span>
|
||||
<span class="sd"> Provides reverse geolocation info for photos </span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> See https://developer.apple.com/documentation/corelocation/clplacemark</span>
|
||||
<span class="sd"> for additional documentation on reverse geolocation data</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd">"""</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">annotations</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">abc</span> <span class="kn">import</span> <span class="n">ABC</span><span class="p">,</span> <span class="n">abstractmethod</span>
|
||||
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span> <span class="c1"># pylint: disable=syntax-error</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">yaml</span>
|
||||
<span class="kn">from</span> <span class="nn">bpylist2</span> <span class="kn">import</span> <span class="n">archiver</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">._constants</span> <span class="kn">import</span> <span class="n">UNICODE_FORMAT</span>
|
||||
<span class="kn">from</span> <span class="nn">.utils</span> <span class="kn">import</span> <span class="n">normalize_unicode</span>
|
||||
<span class="kn">from</span> <span class="nn">.unicode</span> <span class="kn">import</span> <span class="n">normalize_unicode</span>
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="s2">"PLRevGeoLocationInfo"</span><span class="p">,</span>
|
||||
<span class="s2">"PLRevGeoMapItem"</span><span class="p">,</span>
|
||||
<span class="s2">"PLRevGeoMapItemAdditionalPlaceInfo"</span><span class="p">,</span>
|
||||
<span class="s2">"CNPostalAddress"</span><span class="p">,</span>
|
||||
<span class="s2">"PlaceInfo"</span><span class="p">,</span>
|
||||
<span class="s2">"PlaceInfo4"</span><span class="p">,</span>
|
||||
<span class="s2">"PlaceInfo5"</span><span class="p">,</span>
|
||||
<span class="s2">"PLRevGeoLocationInfo"</span><span class="p">,</span>
|
||||
<span class="s2">"PLRevGeoMapItem"</span><span class="p">,</span>
|
||||
<span class="s2">"PLRevGeoMapItemAdditionalPlaceInfo"</span><span class="p">,</span>
|
||||
<span class="s2">"CNPostalAddress"</span><span class="p">,</span>
|
||||
<span class="s2">"PlaceInfo"</span><span class="p">,</span>
|
||||
<span class="s2">"PlaceInfo4"</span><span class="p">,</span>
|
||||
<span class="s2">"PlaceInfo5"</span><span class="p">,</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="c1"># postal address information, returned by PlaceInfo.address</span>
|
||||
<span class="n">PostalAddress</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span>
|
||||
<span class="s2">"PostalAddress"</span><span class="p">,</span>
|
||||
<span class="s2">"PostalAddress"</span><span class="p">,</span>
|
||||
<span class="p">[</span>
|
||||
<span class="s2">"street"</span><span class="p">,</span>
|
||||
<span class="s2">"sub_locality"</span><span class="p">,</span>
|
||||
<span class="s2">"city"</span><span class="p">,</span>
|
||||
<span class="s2">"sub_administrative_area"</span><span class="p">,</span>
|
||||
<span class="s2">"state_province"</span><span class="p">,</span>
|
||||
<span class="s2">"postal_code"</span><span class="p">,</span>
|
||||
<span class="s2">"country"</span><span class="p">,</span>
|
||||
<span class="s2">"iso_country_code"</span><span class="p">,</span>
|
||||
<span class="s2">"street"</span><span class="p">,</span>
|
||||
<span class="s2">"sub_locality"</span><span class="p">,</span>
|
||||
<span class="s2">"city"</span><span class="p">,</span>
|
||||
<span class="s2">"sub_administrative_area"</span><span class="p">,</span>
|
||||
<span class="s2">"state_province"</span><span class="p">,</span>
|
||||
<span class="s2">"postal_code"</span><span class="p">,</span>
|
||||
<span class="s2">"country"</span><span class="p">,</span>
|
||||
<span class="s2">"iso_country_code"</span><span class="p">,</span>
|
||||
<span class="p">],</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
@@ -240,38 +243,39 @@
|
||||
<span class="c1"># PLRevGeoLocationInfo.mapInfo.sortedPlaceInfos</span>
|
||||
<span class="c1"># field 18 is combined bodies of water (ocean + inland_water)</span>
|
||||
<span class="c1"># and maps to Photos <= 4, RKPlace.type == 44</span>
|
||||
<span class="c1"># (Photos <= 4 doesn't have ocean or inland_water types)</span>
|
||||
<span class="c1"># The fields named "field0", etc. appear to be unused</span>
|
||||
<span class="c1"># (Photos <= 4 doesn't have ocean or inland_water types)</span>
|
||||
<span class="c1"># The fields named "field0", etc. appear to be unused</span>
|
||||
<span class="n">PlaceNames</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span>
|
||||
<span class="s2">"PlaceNames"</span><span class="p">,</span>
|
||||
<span class="s2">"PlaceNames"</span><span class="p">,</span>
|
||||
<span class="p">[</span>
|
||||
<span class="s2">"field0"</span><span class="p">,</span>
|
||||
<span class="s2">"country"</span><span class="p">,</span> <span class="c1"># The name of the country associated with the placemark.</span>
|
||||
<span class="s2">"state_province"</span><span class="p">,</span> <span class="c1"># administrativeArea, The state or province associated with the placemark.</span>
|
||||
<span class="s2">"sub_administrative_area"</span><span class="p">,</span> <span class="c1"># Additional administrative area information for the placemark.</span>
|
||||
<span class="s2">"city"</span><span class="p">,</span> <span class="c1"># locality, The city associated with the placemark.</span>
|
||||
<span class="s2">"field5"</span><span class="p">,</span>
|
||||
<span class="s2">"additional_city_info"</span><span class="p">,</span> <span class="c1"># subLocality, Additional city-level information for the placemark.</span>
|
||||
<span class="s2">"ocean"</span><span class="p">,</span> <span class="c1"># The name of the ocean associated with the placemark.</span>
|
||||
<span class="s2">"area_of_interest"</span><span class="p">,</span> <span class="c1"># areasOfInterest, The relevant areas of interest associated with the placemark.</span>
|
||||
<span class="s2">"inland_water"</span><span class="p">,</span> <span class="c1"># The name of the inland water body associated with the placemark.</span>
|
||||
<span class="s2">"field10"</span><span class="p">,</span>
|
||||
<span class="s2">"region"</span><span class="p">,</span> <span class="c1"># The geographic region associated with the placemark.</span>
|
||||
<span class="s2">"sub_throughfare"</span><span class="p">,</span> <span class="c1"># Additional street-level information for the placemark.</span>
|
||||
<span class="s2">"field13"</span><span class="p">,</span>
|
||||
<span class="s2">"postal_code"</span><span class="p">,</span> <span class="c1"># The postal code associated with the placemark.</span>
|
||||
<span class="s2">"field15"</span><span class="p">,</span>
|
||||
<span class="s2">"field16"</span><span class="p">,</span>
|
||||
<span class="s2">"street_address"</span><span class="p">,</span> <span class="c1"># throughfare, The street address associated with the placemark.</span>
|
||||
<span class="s2">"body_of_water"</span><span class="p">,</span> <span class="c1"># RKPlace.type == 44, appears to be any body of water (ocean or inland)</span>
|
||||
<span class="s2">"field0"</span><span class="p">,</span>
|
||||
<span class="s2">"country"</span><span class="p">,</span> <span class="c1"># The name of the country associated with the placemark.</span>
|
||||
<span class="s2">"state_province"</span><span class="p">,</span> <span class="c1"># administrativeArea, The state or province associated with the placemark.</span>
|
||||
<span class="s2">"sub_administrative_area"</span><span class="p">,</span> <span class="c1"># Additional administrative area information for the placemark.</span>
|
||||
<span class="s2">"city"</span><span class="p">,</span> <span class="c1"># locality, The city associated with the placemark.</span>
|
||||
<span class="s2">"field5"</span><span class="p">,</span>
|
||||
<span class="s2">"additional_city_info"</span><span class="p">,</span> <span class="c1"># subLocality, Additional city-level information for the placemark.</span>
|
||||
<span class="s2">"ocean"</span><span class="p">,</span> <span class="c1"># The name of the ocean associated with the placemark.</span>
|
||||
<span class="s2">"area_of_interest"</span><span class="p">,</span> <span class="c1"># areasOfInterest, The relevant areas of interest associated with the placemark.</span>
|
||||
<span class="s2">"inland_water"</span><span class="p">,</span> <span class="c1"># The name of the inland water body associated with the placemark.</span>
|
||||
<span class="s2">"field10"</span><span class="p">,</span>
|
||||
<span class="s2">"region"</span><span class="p">,</span> <span class="c1"># The geographic region associated with the placemark.</span>
|
||||
<span class="s2">"sub_throughfare"</span><span class="p">,</span> <span class="c1"># Additional street-level information for the placemark.</span>
|
||||
<span class="s2">"field13"</span><span class="p">,</span>
|
||||
<span class="s2">"postal_code"</span><span class="p">,</span> <span class="c1"># The postal code associated with the placemark.</span>
|
||||
<span class="s2">"field15"</span><span class="p">,</span>
|
||||
<span class="s2">"field16"</span><span class="p">,</span>
|
||||
<span class="s2">"street_address"</span><span class="p">,</span> <span class="c1"># throughfare, The street address associated with the placemark.</span>
|
||||
<span class="s2">"body_of_water"</span><span class="p">,</span> <span class="c1"># RKPlace.type == 44, appears to be any body of water (ocean or inland)</span>
|
||||
<span class="p">],</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
|
||||
<span class="c1"># The following classes represent Photo Library Reverse Geolocation Info as stored</span>
|
||||
<span class="c1"># in ZADDITIONALASSETATTRIBUTES.ZREVERSELOCATIONDATA</span>
|
||||
<span class="c1"># These classes are used by bpylist.archiver to unarchive the serialized objects</span>
|
||||
<span class="k">class</span> <span class="nc">PLRevGeoLocationInfo</span><span class="p">:</span>
|
||||
<span class="sd">"""The top level reverse geolocation object"""</span>
|
||||
<span class="sd">"""The top level reverse geolocation object"""</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
|
||||
<span class="bp">self</span><span class="p">,</span>
|
||||
@@ -299,14 +303,14 @@
|
||||
<span class="k">return</span> <span class="nb">all</span><span class="p">(</span>
|
||||
<span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="o">==</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span>
|
||||
<span class="s2">"addressString"</span><span class="p">,</span>
|
||||
<span class="s2">"countryCode"</span><span class="p">,</span>
|
||||
<span class="s2">"isHome"</span><span class="p">,</span>
|
||||
<span class="s2">"compoundNames"</span><span class="p">,</span>
|
||||
<span class="s2">"compoundSecondaryNames"</span><span class="p">,</span>
|
||||
<span class="s2">"version"</span><span class="p">,</span>
|
||||
<span class="s2">"geoServiceProvider"</span><span class="p">,</span>
|
||||
<span class="s2">"postalAddress"</span><span class="p">,</span>
|
||||
<span class="s2">"addressString"</span><span class="p">,</span>
|
||||
<span class="s2">"countryCode"</span><span class="p">,</span>
|
||||
<span class="s2">"isHome"</span><span class="p">,</span>
|
||||
<span class="s2">"compoundNames"</span><span class="p">,</span>
|
||||
<span class="s2">"compoundSecondaryNames"</span><span class="p">,</span>
|
||||
<span class="s2">"version"</span><span class="p">,</span>
|
||||
<span class="s2">"geoServiceProvider"</span><span class="p">,</span>
|
||||
<span class="s2">"postalAddress"</span><span class="p">,</span>
|
||||
<span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
@@ -314,31 +318,31 @@
|
||||
<span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__eq__</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"addressString: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">addressString</span><span class="si">}</span><span class="s2">, countryCode: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">countryCode</span><span class="si">}</span><span class="s2">, isHome: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">isHome</span><span class="si">}</span><span class="s2">, mapItem: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">mapItem</span><span class="si">}</span><span class="s2">, postalAddress: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">postalAddress</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"addressString: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">addressString</span><span class="si">}</span><span class="s2">, countryCode: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">countryCode</span><span class="si">}</span><span class="s2">, isHome: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">isHome</span><span class="si">}</span><span class="s2">, mapItem: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">mapItem</span><span class="si">}</span><span class="s2">, postalAddress: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">postalAddress</span><span class="si">}</span><span class="s2">"</span>
|
||||
|
||||
<span class="nd">@staticmethod</span>
|
||||
<span class="k">def</span> <span class="nf">encode_archive</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">archive</span><span class="p">):</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"addressString"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">addressString</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"countryCode"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">countryCode</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"mapItem"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">mapItem</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"isHome"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">isHome</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"compoundNames"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">compoundNames</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"compoundSecondaryNames"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">compoundSecondaryNames</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"version"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">version</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"geoServiceProvider"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">geoServiceProvider</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"postalAddress"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">postalAddress</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"addressString"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">addressString</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"countryCode"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">countryCode</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"mapItem"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">mapItem</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"isHome"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">isHome</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"compoundNames"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">compoundNames</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"compoundSecondaryNames"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">compoundSecondaryNames</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"version"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">version</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"geoServiceProvider"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">geoServiceProvider</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"postalAddress"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">postalAddress</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@staticmethod</span>
|
||||
<span class="k">def</span> <span class="nf">decode_archive</span><span class="p">(</span><span class="n">archive</span><span class="p">):</span>
|
||||
<span class="n">addressString</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"addressString"</span><span class="p">)</span>
|
||||
<span class="n">countryCode</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"countryCode"</span><span class="p">)</span>
|
||||
<span class="n">mapItem</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"mapItem"</span><span class="p">)</span>
|
||||
<span class="n">isHome</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"isHome"</span><span class="p">)</span>
|
||||
<span class="n">compoundNames</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"compoundNames"</span><span class="p">)</span>
|
||||
<span class="n">compoundSecondaryNames</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"compoundSecondaryNames"</span><span class="p">)</span>
|
||||
<span class="n">version</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"version"</span><span class="p">)</span>
|
||||
<span class="n">geoServiceProvider</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"geoServiceProvider"</span><span class="p">)</span>
|
||||
<span class="n">postalAddress</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"postalAddress"</span><span class="p">)</span>
|
||||
<span class="n">addressString</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"addressString"</span><span class="p">)</span>
|
||||
<span class="n">countryCode</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"countryCode"</span><span class="p">)</span>
|
||||
<span class="n">mapItem</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"mapItem"</span><span class="p">)</span>
|
||||
<span class="n">isHome</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"isHome"</span><span class="p">)</span>
|
||||
<span class="n">compoundNames</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"compoundNames"</span><span class="p">)</span>
|
||||
<span class="n">compoundSecondaryNames</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"compoundSecondaryNames"</span><span class="p">)</span>
|
||||
<span class="n">version</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"version"</span><span class="p">)</span>
|
||||
<span class="n">geoServiceProvider</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"geoServiceProvider"</span><span class="p">)</span>
|
||||
<span class="n">postalAddress</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"postalAddress"</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">PLRevGeoLocationInfo</span><span class="p">(</span>
|
||||
<span class="n">addressString</span><span class="p">,</span>
|
||||
<span class="n">countryCode</span><span class="p">,</span>
|
||||
@@ -353,7 +357,7 @@
|
||||
|
||||
|
||||
<span class="k">class</span> <span class="nc">PLRevGeoMapItem</span><span class="p">:</span>
|
||||
<span class="sd">"""Stores the list of place names, organized by area"""</span>
|
||||
<span class="sd">"""Stores the list of place names, organized by area"""</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sortedPlaceInfos</span><span class="p">,</span> <span class="n">finalPlaceInfos</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">sortedPlaceInfos</span> <span class="o">=</span> <span class="n">sortedPlaceInfos</span>
|
||||
@@ -362,7 +366,7 @@
|
||||
<span class="k">def</span> <span class="fm">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="nb">all</span><span class="p">(</span>
|
||||
<span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="o">==</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"sortedPlaceInfos"</span><span class="p">,</span> <span class="s2">"finalPlaceInfos"</span><span class="p">]</span>
|
||||
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"sortedPlaceInfos"</span><span class="p">,</span> <span class="s2">"finalPlaceInfos"</span><span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__ne__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
||||
@@ -372,23 +376,23 @@
|
||||
<span class="n">sortedPlaceInfos</span> <span class="o">=</span> <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">place</span><span class="p">)</span> <span class="k">for</span> <span class="n">place</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">sortedPlaceInfos</span><span class="p">]</span>
|
||||
<span class="n">finalPlaceInfos</span> <span class="o">=</span> <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">place</span><span class="p">)</span> <span class="k">for</span> <span class="n">place</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">finalPlaceInfos</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"finalPlaceInfos: </span><span class="si">{</span><span class="n">finalPlaceInfos</span><span class="si">}</span><span class="s2">, sortedPlaceInfos: </span><span class="si">{</span><span class="n">sortedPlaceInfos</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="sa">f</span><span class="s2">"finalPlaceInfos: </span><span class="si">{</span><span class="n">finalPlaceInfos</span><span class="si">}</span><span class="s2">, sortedPlaceInfos: </span><span class="si">{</span><span class="n">sortedPlaceInfos</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="nd">@staticmethod</span>
|
||||
<span class="k">def</span> <span class="nf">encode_archive</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">archive</span><span class="p">):</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"sortedPlaceInfos"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">sortedPlaceInfos</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"finalPlaceInfos"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">finalPlaceInfos</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"sortedPlaceInfos"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">sortedPlaceInfos</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"finalPlaceInfos"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">finalPlaceInfos</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@staticmethod</span>
|
||||
<span class="k">def</span> <span class="nf">decode_archive</span><span class="p">(</span><span class="n">archive</span><span class="p">):</span>
|
||||
<span class="n">sortedPlaceInfos</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"sortedPlaceInfos"</span><span class="p">)</span>
|
||||
<span class="n">finalPlaceInfos</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"finalPlaceInfos"</span><span class="p">)</span>
|
||||
<span class="n">sortedPlaceInfos</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"sortedPlaceInfos"</span><span class="p">)</span>
|
||||
<span class="n">finalPlaceInfos</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"finalPlaceInfos"</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">PLRevGeoMapItem</span><span class="p">(</span><span class="n">sortedPlaceInfos</span><span class="p">,</span> <span class="n">finalPlaceInfos</span><span class="p">)</span>
|
||||
|
||||
|
||||
<span class="k">class</span> <span class="nc">PLRevGeoMapItemAdditionalPlaceInfo</span><span class="p">:</span>
|
||||
<span class="sd">"""Additional info about individual places"""</span>
|
||||
<span class="sd">"""Additional info about individual places"""</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">area</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">placeType</span><span class="p">,</span> <span class="n">dominantOrderType</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">area</span> <span class="o">=</span> <span class="n">area</span>
|
||||
@@ -399,35 +403,35 @@
|
||||
<span class="k">def</span> <span class="fm">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="nb">all</span><span class="p">(</span>
|
||||
<span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="o">==</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"area"</span><span class="p">,</span> <span class="s2">"name"</span><span class="p">,</span> <span class="s2">"placeType"</span><span class="p">,</span> <span class="s2">"dominantOrderType"</span><span class="p">]</span>
|
||||
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"area"</span><span class="p">,</span> <span class="s2">"name"</span><span class="p">,</span> <span class="s2">"placeType"</span><span class="p">,</span> <span class="s2">"dominantOrderType"</span><span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__ne__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__eq__</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"area: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="si">}</span><span class="s2">, name: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">, placeType: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">placeType</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="k">return</span> <span class="sa">f</span><span class="s2">"area: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">area</span><span class="si">}</span><span class="s2">, name: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">, placeType: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">placeType</span><span class="si">}</span><span class="s2">"</span>
|
||||
|
||||
<span class="nd">@staticmethod</span>
|
||||
<span class="k">def</span> <span class="nf">encode_archive</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">archive</span><span class="p">):</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"area"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">area</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"name"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"placeType"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">placeType</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"dominantOrderType"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">dominantOrderType</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"area"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">area</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"name"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"placeType"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">placeType</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"dominantOrderType"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">dominantOrderType</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@staticmethod</span>
|
||||
<span class="k">def</span> <span class="nf">decode_archive</span><span class="p">(</span><span class="n">archive</span><span class="p">):</span>
|
||||
<span class="n">area</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"area"</span><span class="p">)</span>
|
||||
<span class="n">name</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"name"</span><span class="p">)</span>
|
||||
<span class="n">placeType</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"placeType"</span><span class="p">)</span>
|
||||
<span class="n">dominantOrderType</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"dominantOrderType"</span><span class="p">)</span>
|
||||
<span class="n">area</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"area"</span><span class="p">)</span>
|
||||
<span class="n">name</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"name"</span><span class="p">)</span>
|
||||
<span class="n">placeType</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"placeType"</span><span class="p">)</span>
|
||||
<span class="n">dominantOrderType</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"dominantOrderType"</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">PLRevGeoMapItemAdditionalPlaceInfo</span><span class="p">(</span>
|
||||
<span class="n">area</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">placeType</span><span class="p">,</span> <span class="n">dominantOrderType</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
|
||||
<span class="k">class</span> <span class="nc">CNPostalAddress</span><span class="p">:</span>
|
||||
<span class="sd">"""postal address for the reverse geolocation info"""</span>
|
||||
<span class="sd">"""postal address for the reverse geolocation info"""</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
|
||||
<span class="bp">self</span><span class="p">,</span>
|
||||
@@ -453,14 +457,14 @@
|
||||
<span class="k">return</span> <span class="nb">all</span><span class="p">(</span>
|
||||
<span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span> <span class="o">==</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span>
|
||||
<span class="s2">"_ISOCountryCode"</span><span class="p">,</span>
|
||||
<span class="s2">"_city"</span><span class="p">,</span>
|
||||
<span class="s2">"_country"</span><span class="p">,</span>
|
||||
<span class="s2">"_postalCode"</span><span class="p">,</span>
|
||||
<span class="s2">"_state"</span><span class="p">,</span>
|
||||
<span class="s2">"_street"</span><span class="p">,</span>
|
||||
<span class="s2">"_subAdministrativeArea"</span><span class="p">,</span>
|
||||
<span class="s2">"_subLocality"</span><span class="p">,</span>
|
||||
<span class="s2">"_ISOCountryCode"</span><span class="p">,</span>
|
||||
<span class="s2">"_city"</span><span class="p">,</span>
|
||||
<span class="s2">"_country"</span><span class="p">,</span>
|
||||
<span class="s2">"_postalCode"</span><span class="p">,</span>
|
||||
<span class="s2">"_state"</span><span class="p">,</span>
|
||||
<span class="s2">"_street"</span><span class="p">,</span>
|
||||
<span class="s2">"_subAdministrativeArea"</span><span class="p">,</span>
|
||||
<span class="s2">"_subLocality"</span><span class="p">,</span>
|
||||
<span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
@@ -468,7 +472,7 @@
|
||||
<span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__eq__</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
|
||||
<span class="k">return</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
|
||||
<span class="nb">map</span><span class="p">(</span>
|
||||
<span class="nb">str</span><span class="p">,</span>
|
||||
<span class="p">[</span>
|
||||
@@ -486,25 +490,25 @@
|
||||
|
||||
<span class="nd">@staticmethod</span>
|
||||
<span class="k">def</span> <span class="nf">encode_archive</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">archive</span><span class="p">):</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_ISOCountryCode"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_ISOCountryCode</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_country"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_country</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_city"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_city</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_postalCode"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_postalCode</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_state"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_state</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_street"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_street</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_subAdministrativeArea"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_subAdministrativeArea</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_subLocality"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_subLocality</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_ISOCountryCode"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_ISOCountryCode</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_country"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_country</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_city"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_city</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_postalCode"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_postalCode</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_state"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_state</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_street"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_street</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_subAdministrativeArea"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_subAdministrativeArea</span><span class="p">)</span>
|
||||
<span class="n">archive</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">"_subLocality"</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">_subLocality</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@staticmethod</span>
|
||||
<span class="k">def</span> <span class="nf">decode_archive</span><span class="p">(</span><span class="n">archive</span><span class="p">):</span>
|
||||
<span class="n">_ISOCountryCode</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_ISOCountryCode"</span><span class="p">)</span>
|
||||
<span class="n">_country</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_country"</span><span class="p">)</span>
|
||||
<span class="n">_city</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_city"</span><span class="p">)</span>
|
||||
<span class="n">_postalCode</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_postalCode"</span><span class="p">)</span>
|
||||
<span class="n">_state</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_state"</span><span class="p">)</span>
|
||||
<span class="n">_street</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_street"</span><span class="p">)</span>
|
||||
<span class="n">_subAdministrativeArea</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_subAdministrativeArea"</span><span class="p">)</span>
|
||||
<span class="n">_subLocality</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_subLocality"</span><span class="p">)</span>
|
||||
<span class="n">_ISOCountryCode</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_ISOCountryCode"</span><span class="p">)</span>
|
||||
<span class="n">_country</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_country"</span><span class="p">)</span>
|
||||
<span class="n">_city</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_city"</span><span class="p">)</span>
|
||||
<span class="n">_postalCode</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_postalCode"</span><span class="p">)</span>
|
||||
<span class="n">_state</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_state"</span><span class="p">)</span>
|
||||
<span class="n">_street</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_street"</span><span class="p">)</span>
|
||||
<span class="n">_subAdministrativeArea</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_subAdministrativeArea"</span><span class="p">)</span>
|
||||
<span class="n">_subLocality</span> <span class="o">=</span> <span class="n">archive</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"_subLocality"</span><span class="p">)</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">CNPostalAddress</span><span class="p">(</span>
|
||||
<span class="n">_ISOCountryCode</span><span class="p">,</span>
|
||||
@@ -519,59 +523,124 @@
|
||||
|
||||
|
||||
<span class="c1"># register the classes with bpylist.archiver</span>
|
||||
<span class="n">archiver</span><span class="o">.</span><span class="n">update_class_map</span><span class="p">({</span><span class="s2">"CNPostalAddress"</span><span class="p">:</span> <span class="n">CNPostalAddress</span><span class="p">})</span>
|
||||
<span class="n">archiver</span><span class="o">.</span><span class="n">update_class_map</span><span class="p">({</span><span class="s2">"CNPostalAddress"</span><span class="p">:</span> <span class="n">CNPostalAddress</span><span class="p">})</span>
|
||||
<span class="n">archiver</span><span class="o">.</span><span class="n">update_class_map</span><span class="p">(</span>
|
||||
<span class="p">{</span><span class="s2">"PLRevGeoMapItemAdditionalPlaceInfo"</span><span class="p">:</span> <span class="n">PLRevGeoMapItemAdditionalPlaceInfo</span><span class="p">}</span>
|
||||
<span class="p">{</span><span class="s2">"PLRevGeoMapItemAdditionalPlaceInfo"</span><span class="p">:</span> <span class="n">PLRevGeoMapItemAdditionalPlaceInfo</span><span class="p">}</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">archiver</span><span class="o">.</span><span class="n">update_class_map</span><span class="p">({</span><span class="s2">"PLRevGeoMapItem"</span><span class="p">:</span> <span class="n">PLRevGeoMapItem</span><span class="p">})</span>
|
||||
<span class="n">archiver</span><span class="o">.</span><span class="n">update_class_map</span><span class="p">({</span><span class="s2">"PLRevGeoLocationInfo"</span><span class="p">:</span> <span class="n">PLRevGeoLocationInfo</span><span class="p">})</span>
|
||||
<span class="n">archiver</span><span class="o">.</span><span class="n">update_class_map</span><span class="p">({</span><span class="s2">"PLRevGeoMapItem"</span><span class="p">:</span> <span class="n">PLRevGeoMapItem</span><span class="p">})</span>
|
||||
<span class="n">archiver</span><span class="o">.</span><span class="n">update_class_map</span><span class="p">({</span><span class="s2">"PLRevGeoLocationInfo"</span><span class="p">:</span> <span class="n">PLRevGeoLocationInfo</span><span class="p">})</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="PlaceInfo"><a class="viewcode-back" href="../../reference.html#osxphotos.PlaceInfo">[docs]</a><span class="k">class</span> <span class="nc">PlaceInfo</span><span class="p">(</span><span class="n">ABC</span><span class="p">):</span>
|
||||
<span class="c1"># PlaceInfo is really an abstract base class but defining it as such</span>
|
||||
<span class="c1"># means it doesn't get picked up by the doc generation tools</span>
|
||||
<span class="c1"># so we define it as a regular class and then subclass it</span>
|
||||
<span class="c1"># TODO: right fix is probably have PlaceInfo as the only class that</span>
|
||||
<span class="c1"># is used and then have PlaceInfo4 and PlaceInfo5 called by PlaceInfo</span>
|
||||
<span class="c1"># as needed to return the properties (and make them private classes)</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="PlaceInfo"><a class="viewcode-back" href="../../reference.html#osxphotos.PlaceInfo">[docs]</a><span class="k">class</span> <span class="nc">PlaceInfo</span><span class="p">:</span>
|
||||
<span class="sd">"""Reverse geolocation place info for a photo."""</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="nd">@abstractmethod</span>
|
||||
<span class="k">def</span> <span class="nf">address_str</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">def</span> <span class="nf">address_str</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span> <span class="o">|</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="sd">"""Returns the full postal address as a string if defined, otherwise `None`."""</span>
|
||||
<span class="k">pass</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="nd">@abstractmethod</span>
|
||||
<span class="k">def</span> <span class="nf">country_code</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">def</span> <span class="nf">country_code</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span> <span class="o">|</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="sd">"""Returns the country_code of place, for example "GB".</span>
|
||||
<span class="sd"> Returns `None` if PhotoInfo contains no country code.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">pass</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="nd">@abstractmethod</span>
|
||||
<span class="k">def</span> <span class="nf">ishome</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">def</span> <span class="nf">ishome</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">bool</span><span class="p">:</span>
|
||||
<span class="sd">"""Returns `True` if photo place is user's home address, otherwise `False`."""</span>
|
||||
<span class="k">pass</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="nd">@abstractmethod</span>
|
||||
<span class="k">def</span> <span class="nf">name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">def</span> <span class="nf">name</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span> <span class="o">|</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="sd">"""Returns the name of the local place as str.</span>
|
||||
<span class="sd"> This is what Photos displays in the Info window.</span>
|
||||
<span class="sd"> **Note** Photos 5 uses a different algorithm to determine the name than earlier versions which means the same Photo may have a different place name in Photos 4 and Photos 5.</span>
|
||||
<span class="sd"> `PhotoInfo.name` will return the name Photos would have shown depending on the version of the library being processed.</span>
|
||||
<span class="sd"> Returns `None` if photo does not contain a name.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">pass</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="nd">@abstractmethod</span>
|
||||
<span class="k">def</span> <span class="nf">names</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">def</span> <span class="nf">names</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">PlaceNames</span> <span class="o">|</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="sd">"""Returns a `PlaceNames` namedtuple with the following fields.</span>
|
||||
<span class="sd"> Each field is a list with zero or more values, sorted by area in ascending order.</span>
|
||||
<span class="sd"> E.g. `names.area_of_interest` could be ['Gulf Islands National Seashore', 'Santa Rosa Island'], ["Knott's Berry Farm"], or [] if `area_of_interest` not defined.</span>
|
||||
<span class="sd"> The value shown in Photos is the first value in the list. With the exception of `body_of_water` each of these field corresponds to an attribute of</span>
|
||||
<span class="sd"> a [CLPlacemark](https://developer.apple.com/documentation/corelocation/clplacemark) object.</span>
|
||||
|
||||
|
||||
<span class="sd"> * `country`; the name of the country associated with the placemark.</span>
|
||||
<span class="sd"> * `state_province`; administrativeArea, The state or province associated with the placemark.</span>
|
||||
<span class="sd"> * `sub_administrative_area`; additional administrative area information for the placemark.</span>
|
||||
<span class="sd"> * `city`; locality; the city associated with the placemark.</span>
|
||||
<span class="sd"> * `additional_city_info`; subLocality, Additional city-level information for the placemark.</span>
|
||||
<span class="sd"> * `ocean`; the name of the ocean associated with the placemark.</span>
|
||||
<span class="sd"> * `area_of_interest`; areasOfInterest, The relevant areas of interest associated with the placemark.</span>
|
||||
<span class="sd"> * `inland_water`; the name of the inland water body associated with the placemark.</span>
|
||||
<span class="sd"> * `region`; the geographic region associated with the placemark.</span>
|
||||
<span class="sd"> * `sub_throughfare`; additional street-level information for the placemark.</span>
|
||||
<span class="sd"> * `postal_code`; the postal code associated with the placemark.</span>
|
||||
<span class="sd"> * `street_address`; throughfare, The street address associated with the placemark.</span>
|
||||
<span class="sd"> * `body_of_water`; in Photos 4, any body of water; in Photos 5 contains the union of ocean and inland_water</span>
|
||||
|
||||
<span class="sd"> **Note**: In Photos <= 4.0, only the following fields are defined; all others are set to empty list:</span>
|
||||
|
||||
<span class="sd"> * `country`</span>
|
||||
<span class="sd"> * `state_province`</span>
|
||||
<span class="sd"> * `sub_administrative_area`</span>
|
||||
<span class="sd"> * `city`</span>
|
||||
<span class="sd"> * `additional_city_info`</span>
|
||||
<span class="sd"> * `area_of_interest`</span>
|
||||
<span class="sd"> * `body_of_water`</span>
|
||||
|
||||
<span class="sd"> Note:</span>
|
||||
<span class="sd"> The `PlaceNames` namedtuple contains reserved fields not listed below (see implementation for details),</span>
|
||||
<span class="sd"> thus it should be referenced only by name (e.g. `names.city`) and not by index.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">pass</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="nd">@abstractmethod</span>
|
||||
<span class="k">def</span> <span class="nf">address</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">pass</span></div>
|
||||
<span class="sd">"""Returns a `PostalAddress` namedtuple with details of the postal address containing the following fields:</span>
|
||||
|
||||
<span class="sd"> * `city`</span>
|
||||
<span class="sd"> * `country`</span>
|
||||
<span class="sd"> * `postal_code`</span>
|
||||
<span class="sd"> * `state`</span>
|
||||
<span class="sd"> * `street`</span>
|
||||
<span class="sd"> * `sub_administrative_area`</span>
|
||||
<span class="sd"> * `sub_locality`</span>
|
||||
<span class="sd"> * `iso_country_code`</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">pass</span>
|
||||
|
||||
<div class="viewcode-block" id="PlaceInfo.asdict"><a class="viewcode-back" href="../../reference.html#osxphotos.PlaceInfo.asdict">[docs]</a> <span class="k">def</span> <span class="nf">asdict</span><span class="p">():</span>
|
||||
<span class="sd">"""Returns a dictionary representation of the PlaceInfo object."""</span>
|
||||
<span class="k">pass</span></div></div>
|
||||
|
||||
|
||||
<span class="k">class</span> <span class="nc">PlaceInfo4</span><span class="p">(</span><span class="n">PlaceInfo</span><span class="p">):</span>
|
||||
<span class="sd">"""Reverse geolocation place info for a photo (Photos <= 4)"""</span>
|
||||
<span class="sd">"""Reverse geolocation place info for a photo (Photos <= 4)"""</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">place_names</span><span class="p">,</span> <span class="n">country_code</span><span class="p">):</span>
|
||||
<span class="sd">"""place_names: list of place name tuples in ascending order by area</span>
|
||||
<span class="sd">"""place_names: list of place name tuples in ascending order by area</span>
|
||||
<span class="sd"> tuple fields are: modelID, place name, place type, area, e.g.</span>
|
||||
<span class="sd"> [(5, "St James's Park", 45, 0),</span>
|
||||
<span class="sd"> (4, 'Westminster', 16, 22097376),</span>
|
||||
<span class="sd"> (3, 'London', 4, 1596146816),</span>
|
||||
<span class="sd"> (2, 'England', 2, 180406091776),</span>
|
||||
<span class="sd"> (1, 'United Kingdom', 1, 414681432064)]</span>
|
||||
<span class="sd"> [(5, "St James's Park", 45, 0),</span>
|
||||
<span class="sd"> (4, 'Westminster', 16, 22097376),</span>
|
||||
<span class="sd"> (3, 'London', 4, 1596146816),</span>
|
||||
<span class="sd"> (2, 'England', 2, 180406091776),</span>
|
||||
<span class="sd"> (1, 'United Kingdom', 1, 414681432064)]</span>
|
||||
<span class="sd"> country_code: two letter country code for the country</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_place_names</span> <span class="o">=</span> <span class="n">place_names</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_country_code</span> <span class="o">=</span> <span class="n">country_code</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_process_place_info</span><span class="p">()</span>
|
||||
@@ -610,14 +679,14 @@
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_process_place_info</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Process place_names to set self._name and self._names"""</span>
|
||||
<span class="sd">"""Process place_names to set self._name and self._names"""</span>
|
||||
<span class="n">places</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_place_names</span>
|
||||
|
||||
<span class="c1"># build a dictionary where key is placetype</span>
|
||||
<span class="n">places_dict</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
<span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">places</span><span class="p">:</span>
|
||||
<span class="c1"># places in format:</span>
|
||||
<span class="c1"># [(5, "St James's Park", 45, 0), ]</span>
|
||||
<span class="c1"># [(5, "St James's Park", 45, 0), ]</span>
|
||||
<span class="c1"># 0: modelID</span>
|
||||
<span class="c1"># 1: name</span>
|
||||
<span class="c1"># 2: type</span>
|
||||
@@ -659,7 +728,7 @@
|
||||
|
||||
<span class="c1"># build the name as it appears in Photos</span>
|
||||
<span class="c1"># the length of the name is at most 3 fields and appears to be based on available</span>
|
||||
<span class="c1"># reverse geolocation data in the following order (left to right, joined by ',')</span>
|
||||
<span class="c1"># reverse geolocation data in the following order (left to right, joined by ',')</span>
|
||||
<span class="c1"># always has country if available then either area of interest and city OR</span>
|
||||
<span class="c1"># city and state</span>
|
||||
<span class="c1"># e.g. 4, 2, 1 OR 8, 4, 1</span>
|
||||
@@ -683,61 +752,61 @@
|
||||
<span class="k">if</span> <span class="n">place_names</span><span class="p">[</span><span class="mi">1</span><span class="p">]:</span>
|
||||
<span class="n">name_list</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">place_names</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
|
||||
|
||||
<span class="n">name</span> <span class="o">=</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">name_list</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_name</span> <span class="o">=</span> <span class="n">name</span> <span class="k">if</span> <span class="n">name</span> <span class="o">!=</span> <span class="s2">""</span> <span class="k">else</span> <span class="kc">None</span>
|
||||
<span class="n">name</span> <span class="o">=</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">name_list</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_name</span> <span class="o">=</span> <span class="n">name</span> <span class="k">if</span> <span class="n">name</span> <span class="o">!=</span> <span class="s2">""</span> <span class="k">else</span> <span class="kc">None</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__ne__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__eq__</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="n">info</span> <span class="o">=</span> <span class="p">{</span>
|
||||
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||||
<span class="s2">"names"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">names</span><span class="p">,</span>
|
||||
<span class="s2">"country_code"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">country_code</span><span class="p">,</span>
|
||||
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||||
<span class="s2">"names"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">names</span><span class="p">,</span>
|
||||
<span class="s2">"country_code"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">country_code</span><span class="p">,</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">return</span> <span class="s2">"PlaceInfo("</span> <span class="o">+</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">k</span><span class="si">}</span><span class="s2">='</span><span class="si">{</span><span class="n">v</span><span class="si">}</span><span class="s2">'"</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">info</span><span class="o">.</span><span class="n">items</span><span class="p">()])</span> <span class="o">+</span> <span class="s2">")"</span>
|
||||
<span class="k">return</span> <span class="s2">"PlaceInfo("</span> <span class="o">+</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">k</span><span class="si">}</span><span class="s2">='</span><span class="si">{</span><span class="n">v</span><span class="si">}</span><span class="s2">'"</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">info</span><span class="o">.</span><span class="n">items</span><span class="p">()])</span> <span class="o">+</span> <span class="s2">")"</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="p">{</span>
|
||||
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||||
<span class="s2">"names"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">names</span><span class="o">.</span><span class="n">_asdict</span><span class="p">(),</span>
|
||||
<span class="s2">"country_code"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">country_code</span><span class="p">,</span>
|
||||
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||||
<span class="s2">"names"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">names</span><span class="o">.</span><span class="n">_asdict</span><span class="p">(),</span>
|
||||
<span class="s2">"country_code"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">country_code</span><span class="p">,</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
|
||||
<span class="k">class</span> <span class="nc">PlaceInfo5</span><span class="p">(</span><span class="n">PlaceInfo</span><span class="p">):</span>
|
||||
<span class="sd">"""Reverse geolocation place info for a photo (Photos >= 5)"""</span>
|
||||
<span class="sd">"""Reverse geolocation place info for a photo (Photos >= 5)"""</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">revgeoloc_bplist</span><span class="p">):</span>
|
||||
<span class="sd">"""revgeoloc_bplist: a binary plist blob containing</span>
|
||||
<span class="sd"> a serialized PLRevGeoLocationInfo object"""</span>
|
||||
<span class="sd">"""revgeoloc_bplist: a binary plist blob containing</span>
|
||||
<span class="sd"> a serialized PLRevGeoLocationInfo object"""</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_bplist</span> <span class="o">=</span> <span class="n">revgeoloc_bplist</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_plrevgeoloc</span> <span class="o">=</span> <span class="n">archiver</span><span class="o">.</span><span class="n">unarchive</span><span class="p">(</span><span class="n">revgeoloc_bplist</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_process_place_info</span><span class="p">()</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">address_str</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""returns the postal address as a string"""</span>
|
||||
<span class="sd">"""returns the postal address as a string"""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_plrevgeoloc</span><span class="o">.</span><span class="n">addressString</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">country_code</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""returns the country code"""</span>
|
||||
<span class="sd">"""returns the country code"""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_plrevgeoloc</span><span class="o">.</span><span class="n">countryCode</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">ishome</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""returns True if place is user's home address"""</span>
|
||||
<span class="sd">"""returns True if place is user's home address"""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_plrevgeoloc</span><span class="o">.</span><span class="n">isHome</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""returns local place name"""</span>
|
||||
<span class="sd">"""returns local place name"""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_name</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">names</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""returns PlaceNames tuple with detailed reverse geolocation place names"""</span>
|
||||
<span class="sd">"""returns PlaceNames tuple with detailed reverse geolocation place names"""</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_names</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
@@ -762,7 +831,7 @@
|
||||
<span class="k">return</span> <span class="n">postal_address</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_process_place_info</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Process sortedPlaceInfos to set self._name and self._names"""</span>
|
||||
<span class="sd">"""Process sortedPlaceInfos to set self._name and self._names"""</span>
|
||||
<span class="n">places</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_plrevgeoloc</span><span class="o">.</span><span class="n">mapItem</span><span class="o">.</span><span class="n">sortedPlaceInfos</span>
|
||||
|
||||
<span class="c1"># build a dictionary where key is placetype</span>
|
||||
@@ -795,20 +864,20 @@
|
||||
|
||||
<span class="c1"># build the name as it appears in Photos</span>
|
||||
<span class="c1"># the length of the name is variable and appears to be based on available</span>
|
||||
<span class="c1"># reverse geolocation data in the following order (left to right, joined by ',')</span>
|
||||
<span class="c1"># reverse geolocation data in the following order (left to right, joined by ',')</span>
|
||||
<span class="c1"># 8: area_of_interest</span>
|
||||
<span class="c1"># 11: region (I've only seen this applied to islands)</span>
|
||||
<span class="c1"># 11: region (I've only seen this applied to islands)</span>
|
||||
<span class="c1"># 4: locality / city</span>
|
||||
<span class="c1"># 2: administrative area (state/province)</span>
|
||||
<span class="c1"># 1: country</span>
|
||||
<span class="c1"># 9: inland_water</span>
|
||||
<span class="c1"># 7: ocean</span>
|
||||
<span class="n">name</span> <span class="o">=</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
|
||||
<span class="n">name</span> <span class="o">=</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
|
||||
<span class="p">[</span>
|
||||
<span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="p">[</span>
|
||||
<span class="n">place_names</span><span class="p">[</span><span class="mi">8</span><span class="p">],</span> <span class="c1"># area of interest</span>
|
||||
<span class="n">place_names</span><span class="p">[</span><span class="mi">11</span><span class="p">],</span> <span class="c1"># region (I've only seen this applied to islands)</span>
|
||||
<span class="n">place_names</span><span class="p">[</span><span class="mi">11</span><span class="p">],</span> <span class="c1"># region (I've only seen this applied to islands)</span>
|
||||
<span class="n">place_names</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="c1"># locality / city</span>
|
||||
<span class="n">place_names</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="c1"># administrative area (state/province)</span>
|
||||
<span class="n">place_names</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="c1"># country</span>
|
||||
@@ -818,7 +887,7 @@
|
||||
<span class="k">if</span> <span class="n">p</span> <span class="ow">and</span> <span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_name</span> <span class="o">=</span> <span class="n">name</span> <span class="k">if</span> <span class="n">name</span> <span class="o">!=</span> <span class="s2">""</span> <span class="k">else</span> <span class="kc">None</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_name</span> <span class="o">=</span> <span class="n">name</span> <span class="k">if</span> <span class="n">name</span> <span class="o">!=</span> <span class="s2">""</span> <span class="k">else</span> <span class="kc">None</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)):</span>
|
||||
@@ -831,23 +900,23 @@
|
||||
|
||||
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="n">info</span> <span class="o">=</span> <span class="p">{</span>
|
||||
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||||
<span class="s2">"names"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">names</span><span class="p">,</span>
|
||||
<span class="s2">"country_code"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">country_code</span><span class="p">,</span>
|
||||
<span class="s2">"ishome"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">ishome</span><span class="p">,</span>
|
||||
<span class="s2">"address_str"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">address_str</span><span class="p">,</span>
|
||||
<span class="s2">"address"</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">address</span><span class="p">),</span>
|
||||
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||||
<span class="s2">"names"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">names</span><span class="p">,</span>
|
||||
<span class="s2">"country_code"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">country_code</span><span class="p">,</span>
|
||||
<span class="s2">"ishome"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">ishome</span><span class="p">,</span>
|
||||
<span class="s2">"address_str"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">address_str</span><span class="p">,</span>
|
||||
<span class="s2">"address"</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">address</span><span class="p">),</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">return</span> <span class="s2">"PlaceInfo("</span> <span class="o">+</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">k</span><span class="si">}</span><span class="s2">='</span><span class="si">{</span><span class="n">v</span><span class="si">}</span><span class="s2">'"</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">info</span><span class="o">.</span><span class="n">items</span><span class="p">()])</span> <span class="o">+</span> <span class="s2">")"</span>
|
||||
<span class="k">return</span> <span class="s2">"PlaceInfo("</span> <span class="o">+</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">k</span><span class="si">}</span><span class="s2">='</span><span class="si">{</span><span class="n">v</span><span class="si">}</span><span class="s2">'"</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">info</span><span class="o">.</span><span class="n">items</span><span class="p">()])</span> <span class="o">+</span> <span class="s2">")"</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="p">{</span>
|
||||
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||||
<span class="s2">"names"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">names</span><span class="o">.</span><span class="n">_asdict</span><span class="p">(),</span>
|
||||
<span class="s2">"country_code"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">country_code</span><span class="p">,</span>
|
||||
<span class="s2">"ishome"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">ishome</span><span class="p">,</span>
|
||||
<span class="s2">"address_str"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">address_str</span><span class="p">,</span>
|
||||
<span class="s2">"address"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span><span class="o">.</span><span class="n">_asdict</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="s2">"name"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||||
<span class="s2">"names"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">names</span><span class="o">.</span><span class="n">_asdict</span><span class="p">(),</span>
|
||||
<span class="s2">"country_code"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">country_code</span><span class="p">,</span>
|
||||
<span class="s2">"ishome"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">ishome</span><span class="p">,</span>
|
||||
<span class="s2">"address_str"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">address_str</span><span class="p">,</span>
|
||||
<span class="s2">"address"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span><span class="o">.</span><span class="n">_asdict</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</article>
|
||||
@@ -886,7 +955,9 @@
|
||||
</div><script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
|
||||
<script src="../../_static/jquery.js"></script>
|
||||
<script src="../../_static/underscore.js"></script>
|
||||
<script src="../../_static/_sphinx_javascript_frameworks_compat.js"></script>
|
||||
<script src="../../_static/doctools.js"></script>
|
||||
<script src="../../_static/sphinx_highlight.js"></script>
|
||||
<script src="../../_static/scripts/furo.js"></script>
|
||||
<script src="../../_static/clipboard.min.js"></script>
|
||||
<script src="../../_static/copybutton.js"></script>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!doctype html>
|
||||
<html class="no-js">
|
||||
<html class="no-js" lang="en">
|
||||
<head><meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-4.4.0, furo 2022.04.07"/>
|
||||
<title>osxphotos.queryoptions - osxphotos 0.50.13 documentation</title>
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.queryoptions - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=68f4518137b9aefe99b631505a2064c3c42c9852" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.50.13 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.50.13 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -179,7 +179,8 @@
|
||||
</svg>
|
||||
<span>Back to top</span>
|
||||
</a>
|
||||
<div class="content-icon-container"><div class="theme-toggle-container theme-toggle-content">
|
||||
<div class="content-icon-container">
|
||||
<div class="theme-toggle-container theme-toggle-content">
|
||||
<button class="theme-toggle">
|
||||
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
|
||||
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||||
@@ -194,28 +195,41 @@
|
||||
</div>
|
||||
<article role="main">
|
||||
<h1>Source code for osxphotos.queryoptions</h1><div class="highlight"><pre>
|
||||
<span></span><span class="sd">""" QueryOptions class for PhotosDB.query """</span>
|
||||
<span></span><span class="sd">""" QueryOptions class for PhotosDB.query """</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">dataclasses</span>
|
||||
<span class="kn">import</span> <span class="nn">datetime</span>
|
||||
<span class="kn">import</span> <span class="nn">io</span>
|
||||
<span class="kn">import</span> <span class="nn">pathlib</span>
|
||||
<span class="kn">import</span> <span class="nn">re</span>
|
||||
<span class="kn">import</span> <span class="nn">sys</span>
|
||||
<span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">asdict</span><span class="p">,</span> <span class="n">dataclass</span>
|
||||
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Iterable</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">Optional</span><span class="p">,</span> <span class="n">Tuple</span>
|
||||
|
||||
<span class="kn">import</span> <span class="nn">bitmath</span>
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"QueryOptions"</span><span class="p">]</span>
|
||||
<span class="kn">from</span> <span class="nn">._constants</span> <span class="kn">import</span> <span class="n">UUID_PATTERN</span>
|
||||
|
||||
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"QueryOptions"</span><span class="p">,</span> <span class="s2">"query_options_from_kwargs"</span><span class="p">,</span> <span class="s2">"IncompatibleQueryOptions"</span><span class="p">]</span>
|
||||
|
||||
|
||||
<span class="k">class</span> <span class="nc">IncompatibleQueryOptions</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
||||
<span class="sd">"""Incompatible query options"""</span>
|
||||
|
||||
<span class="k">pass</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="QueryOptions"><a class="viewcode-back" href="../../reference.html#osxphotos.QueryOptions">[docs]</a><span class="nd">@dataclass</span>
|
||||
<span class="k">class</span> <span class="nc">QueryOptions</span><span class="p">:</span>
|
||||
|
||||
<span class="sd">"""QueryOptions class for PhotosDB.query</span>
|
||||
<span class="sd">"""QueryOptions class for PhotosDB.query</span>
|
||||
|
||||
<span class="sd"> Attributes:</span>
|
||||
<span class="sd"> added_after: search for photos added after a given date</span>
|
||||
<span class="sd"> added_before: search for photos added before a given date</span>
|
||||
<span class="sd"> added_in_last: search for photos added in last X datetime.timedelta</span>
|
||||
<span class="sd"> album: list of album names to search for</span>
|
||||
<span class="sd"> burst_photos: search for burst photos</span>
|
||||
<span class="sd"> burst_photos: include all associated burst photos for photos in query results</span>
|
||||
<span class="sd"> burst: search for burst photos</span>
|
||||
<span class="sd"> cloudasset: search for photos that are managed by iCloud</span>
|
||||
<span class="sd"> deleted_only: search only for deleted photos</span>
|
||||
@@ -257,6 +271,7 @@
|
||||
<span class="sd"> no_title: search for photos with no title</span>
|
||||
<span class="sd"> not_burst: search for non-burst photos</span>
|
||||
<span class="sd"> not_cloudasset: search for photos that are not managed by iCloud</span>
|
||||
<span class="sd"> not_edited: search for photos that have not been edited</span>
|
||||
<span class="sd"> not_favorite: search for non-favorite photos</span>
|
||||
<span class="sd"> not_hdr: search for non-HDR photos</span>
|
||||
<span class="sd"> not_hidden: search for non-hidden photos</span>
|
||||
@@ -290,7 +305,13 @@
|
||||
<span class="sd"> uti: list of UTIs to search for</span>
|
||||
<span class="sd"> uuid: list of uuids to search for</span>
|
||||
<span class="sd"> year: search for photos taken in a given year</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="sd"> syndicated: search for photos that have been shared via syndication ("Shared with You" album via Messages, etc.)</span>
|
||||
<span class="sd"> not_syndicated: search for photos that have not been shared via syndication ("Shared with You" album via Messages, etc.)</span>
|
||||
<span class="sd"> saved_to_library: search for syndicated photos that have been saved to the Photos library</span>
|
||||
<span class="sd"> not_saved_to_library: search for syndicated photos that have not been saved to the Photos library</span>
|
||||
<span class="sd"> shared_moment: search for photos that have been shared via a shared moment</span>
|
||||
<span class="sd"> not_shared_moment: search for photos that have not been shared via a shared moment</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="n">added_after</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">added_before</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
@@ -339,6 +360,7 @@
|
||||
<span class="n">no_title</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">not_burst</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">not_cloudasset</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">not_edited</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">not_favorite</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">not_hdr</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">not_hidden</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
@@ -373,9 +395,180 @@
|
||||
<span class="n">uti</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</span><span class="p">[</span><span class="nb">str</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">uuid</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</span><span class="p">[</span><span class="nb">str</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">year</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Iterable</span><span class="p">[</span><span class="nb">int</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">syndicated</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">not_syndicated</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">saved_to_library</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">not_saved_to_library</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">shared_moment</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="n">not_shared_moment</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">bool</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="n">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">query_options_from_kwargs</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="o">-></span> <span class="n">QueryOptions</span><span class="p">:</span>
|
||||
<span class="sd">"""Validate query options and create a QueryOptions instance.</span>
|
||||
<span class="sd"> Note: this will block on stdin if uuid_from_file is set to "-"</span>
|
||||
<span class="sd"> so it is best to call function before creating the PhotosDB instance</span>
|
||||
<span class="sd"> so that the validation of query options can happen before the database</span>
|
||||
<span class="sd"> is loaded.</span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="c1"># sanity check input args</span>
|
||||
<span class="n">nonexclusive</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="s2">"added_after"</span><span class="p">,</span>
|
||||
<span class="s2">"added_before"</span><span class="p">,</span>
|
||||
<span class="s2">"added_in_last"</span><span class="p">,</span>
|
||||
<span class="s2">"album"</span><span class="p">,</span>
|
||||
<span class="s2">"duplicate"</span><span class="p">,</span>
|
||||
<span class="s2">"exif"</span><span class="p">,</span>
|
||||
<span class="s2">"external_edit"</span><span class="p">,</span>
|
||||
<span class="s2">"folder"</span><span class="p">,</span>
|
||||
<span class="s2">"from_date"</span><span class="p">,</span>
|
||||
<span class="s2">"from_time"</span><span class="p">,</span>
|
||||
<span class="s2">"has_raw"</span><span class="p">,</span>
|
||||
<span class="s2">"keyword"</span><span class="p">,</span>
|
||||
<span class="s2">"label"</span><span class="p">,</span>
|
||||
<span class="s2">"max_size"</span><span class="p">,</span>
|
||||
<span class="s2">"min_size"</span><span class="p">,</span>
|
||||
<span class="s2">"name"</span><span class="p">,</span>
|
||||
<span class="s2">"person"</span><span class="p">,</span>
|
||||
<span class="s2">"query_eval"</span><span class="p">,</span>
|
||||
<span class="s2">"query_function"</span><span class="p">,</span>
|
||||
<span class="s2">"regex"</span><span class="p">,</span>
|
||||
<span class="s2">"selected"</span><span class="p">,</span>
|
||||
<span class="s2">"to_date"</span><span class="p">,</span>
|
||||
<span class="s2">"to_time"</span><span class="p">,</span>
|
||||
<span class="s2">"uti"</span><span class="p">,</span>
|
||||
<span class="s2">"uuid"</span><span class="p">,</span>
|
||||
<span class="s2">"uuid_from_file"</span><span class="p">,</span>
|
||||
<span class="s2">"year"</span><span class="p">,</span>
|
||||
<span class="p">]</span>
|
||||
<span class="n">exclusive</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="p">(</span><span class="s2">"burst"</span><span class="p">,</span> <span class="s2">"not_burst"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"cloudasset"</span><span class="p">,</span> <span class="s2">"not_cloudasset"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"edited"</span><span class="p">,</span> <span class="s2">"not_edited"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"favorite"</span><span class="p">,</span> <span class="s2">"not_favorite"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"has_comment"</span><span class="p">,</span> <span class="s2">"no_comment"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"has_likes"</span><span class="p">,</span> <span class="s2">"no_likes"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"hdr"</span><span class="p">,</span> <span class="s2">"not_hdr"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"hidden"</span><span class="p">,</span> <span class="s2">"not_hidden"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"in_album"</span><span class="p">,</span> <span class="s2">"not_in_album"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"incloud"</span><span class="p">,</span> <span class="s2">"not_incloud"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"is_reference"</span><span class="p">,</span> <span class="s2">"not_reference"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"keyword"</span><span class="p">,</span> <span class="s2">"no_keyword"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"live"</span><span class="p">,</span> <span class="s2">"not_live"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"location"</span><span class="p">,</span> <span class="s2">"no_location"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"missing"</span><span class="p">,</span> <span class="s2">"not_missing"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"only_photos"</span><span class="p">,</span> <span class="s2">"only_movies"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"panorama"</span><span class="p">,</span> <span class="s2">"not_panorama"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"portrait"</span><span class="p">,</span> <span class="s2">"not_portrait"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"screenshot"</span><span class="p">,</span> <span class="s2">"not_screenshot"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"selfie"</span><span class="p">,</span> <span class="s2">"not_selfie"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"shared"</span><span class="p">,</span> <span class="s2">"not_shared"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"slow_mo"</span><span class="p">,</span> <span class="s2">"not_slow_mo"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"time_lapse"</span><span class="p">,</span> <span class="s2">"not_time_lapse"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"deleted"</span><span class="p">,</span> <span class="s2">"not_deleted"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"deleted"</span><span class="p">,</span> <span class="s2">"deleted_only"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"deleted_only"</span><span class="p">,</span> <span class="s2">"not_deleted"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"syndicated"</span><span class="p">,</span> <span class="s2">"not_syndicated"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"saved_to_library"</span><span class="p">,</span> <span class="s2">"not_saved_to_library"</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="s2">"shared_moment"</span><span class="p">,</span> <span class="s2">"not_shared_moment"</span><span class="p">),</span>
|
||||
<span class="p">]</span>
|
||||
<span class="c1"># TODO: add option to validate requiring at least one query arg</span>
|
||||
<span class="k">for</span> <span class="n">arg</span><span class="p">,</span> <span class="n">not_arg</span> <span class="ow">in</span> <span class="n">exclusive</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span> <span class="ow">and</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">not_arg</span><span class="p">):</span>
|
||||
<span class="n">arg</span> <span class="o">=</span> <span class="n">arg</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"_"</span><span class="p">,</span> <span class="s2">"-"</span><span class="p">)</span>
|
||||
<span class="n">not_arg</span> <span class="o">=</span> <span class="n">not_arg</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"_"</span><span class="p">,</span> <span class="s2">"-"</span><span class="p">)</span>
|
||||
<span class="k">raise</span> <span class="n">IncompatibleQueryOptions</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Incompatible query options: --</span><span class="si">{</span><span class="n">arg</span><span class="si">}</span><span class="s2"> and --</span><span class="si">{</span><span class="n">not_arg</span><span class="si">}</span><span class="s2"> are mutually exclusive"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="c1"># some options like title can be specified multiple times</span>
|
||||
<span class="c1"># check if any of them are specified along with their no_ counterpart</span>
|
||||
<span class="n">exclusive_multi_options</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"title"</span><span class="p">,</span> <span class="s2">"description"</span><span class="p">,</span> <span class="s2">"place"</span><span class="p">,</span> <span class="s2">"keyword"</span><span class="p">]</span>
|
||||
<span class="k">for</span> <span class="n">option</span> <span class="ow">in</span> <span class="n">exclusive_multi_options</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">option</span><span class="p">)</span> <span class="ow">and</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"no_</span><span class="si">{option}</span><span class="s2">"</span><span class="p">):</span>
|
||||
<span class="k">raise</span> <span class="n">IncompatibleQueryOptions</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"--</span><span class="si">{</span><span class="n">option</span><span class="si">}</span><span class="s2"> and --no-</span><span class="si">{</span><span class="n">option</span><span class="si">}</span><span class="s2"> are mutually exclusive"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="n">include_photos</span> <span class="o">=</span> <span class="kc">True</span>
|
||||
<span class="n">include_movies</span> <span class="o">=</span> <span class="kc">True</span> <span class="c1"># default searches for everything</span>
|
||||
<span class="k">if</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"only_movies"</span><span class="p">):</span>
|
||||
<span class="n">include_photos</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
<span class="k">if</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"only_photos"</span><span class="p">):</span>
|
||||
<span class="n">include_movies</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
|
||||
<span class="c1"># load UUIDs if necessary and append to any uuids passed with --uuid</span>
|
||||
<span class="n">uuids</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"uuid"</span><span class="p">,</span> <span class="p">[]))</span> <span class="c1"># Click option is a tuple</span>
|
||||
<span class="k">if</span> <span class="n">uuid_from_file</span> <span class="o">:=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"uuid_from_file"</span><span class="p">):</span>
|
||||
<span class="n">uuids</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">load_uuid_from_file</span><span class="p">(</span><span class="n">uuid_from_file</span><span class="p">))</span>
|
||||
<span class="n">uuids</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">uuids</span><span class="p">)</span>
|
||||
|
||||
<span class="n">query_fields</span> <span class="o">=</span> <span class="p">[</span><span class="n">field</span><span class="o">.</span><span class="n">name</span> <span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">dataclasses</span><span class="o">.</span><span class="n">fields</span><span class="p">(</span><span class="n">QueryOptions</span><span class="p">)]</span>
|
||||
<span class="n">query_dict</span> <span class="o">=</span> <span class="p">{</span><span class="n">field</span><span class="p">:</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">field</span><span class="p">)</span> <span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">query_fields</span><span class="p">}</span>
|
||||
<span class="n">query_dict</span><span class="p">[</span><span class="s2">"photos"</span><span class="p">]</span> <span class="o">=</span> <span class="n">include_photos</span>
|
||||
<span class="n">query_dict</span><span class="p">[</span><span class="s2">"movies"</span><span class="p">]</span> <span class="o">=</span> <span class="n">include_movies</span>
|
||||
<span class="n">query_dict</span><span class="p">[</span><span class="s2">"uuid"</span><span class="p">]</span> <span class="o">=</span> <span class="n">uuids</span>
|
||||
<span class="n">query_dict</span><span class="p">[</span><span class="s2">"function"</span><span class="p">]</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"query_function"</span><span class="p">)</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">QueryOptions</span><span class="p">(</span><span class="o">**</span><span class="n">query_dict</span><span class="p">)</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">load_uuid_from_file</span><span class="p">(</span><span class="n">filename</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">list</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> Load UUIDs from file.</span>
|
||||
<span class="sd"> Does not validate UUIDs but does validate that the UUIDs are in the correct format.</span>
|
||||
<span class="sd"> Format is 1 UUID per line, any line beginning with # is ignored.</span>
|
||||
<span class="sd"> Whitespace is stripped.</span>
|
||||
|
||||
<span class="sd"> Arguments:</span>
|
||||
<span class="sd"> filename: file name of the file containing UUIDs</span>
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> list of UUIDs or empty list of no UUIDs in file</span>
|
||||
|
||||
<span class="sd"> Raises:</span>
|
||||
<span class="sd"> FileNotFoundError if file does not exist</span>
|
||||
<span class="sd"> ValueError if UUID is not in correct format</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">filename</span> <span class="o">==</span> <span class="s2">"-"</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="n">_load_uuid_from_stream</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="p">)</span>
|
||||
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span><span class="o">.</span><span class="n">is_file</span><span class="p">():</span>
|
||||
<span class="k">raise</span> <span class="ne">FileNotFoundError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Could not find file </span><span class="si">{</span><span class="n">filename</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
|
||||
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s2">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="n">_load_uuid_from_stream</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">_load_uuid_from_stream</span><span class="p">(</span><span class="n">stream</span><span class="p">:</span> <span class="n">io</span><span class="o">.</span><span class="n">IOBase</span><span class="p">)</span> <span class="o">-></span> <span class="nb">list</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> Load UUIDs from stream.</span>
|
||||
<span class="sd"> Does not validate UUIDs but does validate that the UUIDs are in the correct format.</span>
|
||||
<span class="sd"> Format is 1 UUID per line, any line beginning with # is ignored.</span>
|
||||
<span class="sd"> Whitespace is stripped.</span>
|
||||
|
||||
<span class="sd"> Arguments:</span>
|
||||
<span class="sd"> filename: file name of the file containing UUIDs</span>
|
||||
|
||||
<span class="sd"> Returns:</span>
|
||||
<span class="sd"> list of UUIDs or empty list of no UUIDs in file</span>
|
||||
|
||||
<span class="sd"> Raises:</span>
|
||||
<span class="sd"> ValueError if UUID is not in correct format</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="n">uuid</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">stream</span><span class="p">:</span>
|
||||
<span class="n">line</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">line</span><span class="p">)</span> <span class="ow">and</span> <span class="n">line</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"#"</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="sa">f</span><span class="s2">"^</span><span class="si">{</span><span class="n">UUID_PATTERN</span><span class="si">}</span><span class="s2">$"</span><span class="p">,</span> <span class="n">line</span><span class="p">):</span>
|
||||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Invalid UUID: </span><span class="si">{</span><span class="n">line</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||||
<span class="n">line</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
|
||||
<span class="n">uuid</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">uuid</span>
|
||||
</pre></div>
|
||||
</article>
|
||||
</div>
|
||||
@@ -413,7 +606,9 @@
|
||||
</div><script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
|
||||
<script src="../../_static/jquery.js"></script>
|
||||
<script src="../../_static/underscore.js"></script>
|
||||
<script src="../../_static/_sphinx_javascript_frameworks_compat.js"></script>
|
||||
<script src="../../_static/doctools.js"></script>
|
||||
<script src="../../_static/sphinx_highlight.js"></script>
|
||||
<script src="../../_static/scripts/furo.js"></script>
|
||||
<script src="../../_static/clipboard.min.js"></script>
|
||||
<script src="../../_static/copybutton.js"></script>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.scoreinfo - osxphotos 0.56.2 documentation</title>
|
||||
<title>osxphotos.scoreinfo - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.56.2 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.56.2 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -197,7 +197,7 @@
|
||||
<h1>Source code for osxphotos.scoreinfo</h1><div class="highlight"><pre>
|
||||
<span></span><span class="sd">""" ScoreInfo class to expose computed score info from the library """</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span><span class="p">,</span> <span class="n">asdict</span>
|
||||
<span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">asdict</span><span class="p">,</span> <span class="n">dataclass</span>
|
||||
|
||||
<span class="kn">from</span> <span class="nn">._constants</span> <span class="kn">import</span> <span class="n">_PHOTOS_4_VERSION</span>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.searchinfo - osxphotos 0.54.1 documentation</title>
|
||||
<title>osxphotos.searchinfo - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.54.1 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.1 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -160,7 +160,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -336,6 +336,13 @@
|
||||
<span class="k">return</span> <span class="p">[]</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_text_for_category</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_categories</span><span class="o">.</span><span class="n">DETECTED_TEXT</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">text_found</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns True if photos has detected text (macOS 13+ / Photos 8+ only)"""</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photo</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_photos_ver</span> <span class="o"><</span> <span class="mi">8</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="p">[]</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_text_for_category</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_categories</span><span class="o">.</span><span class="n">TEXT_FOUND</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">camera</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""returns camera name (macOS 13+ / Photos 8+ only)"""</span>
|
||||
@@ -344,10 +351,18 @@
|
||||
<span class="n">camera</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_text_for_category</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_categories</span><span class="o">.</span><span class="n">CAMERA</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">camera</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">camera</span> <span class="k">else</span> <span class="s2">""</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">source</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""returns source of the photo (e.g. "Messages", "Safar", etc) (macOS 13+ / Photos 8+ only)"""</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_photo</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_photos_ver</span> <span class="o"><</span> <span class="mi">8</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="s2">""</span>
|
||||
<span class="n">source</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_text_for_category</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_categories</span><span class="o">.</span><span class="n">SOURCE</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">source</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">source</span> <span class="k">else</span> <span class="s2">""</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">all</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""return all search info properties in a single list"""</span>
|
||||
<span class="nb">all</span> <span class="o">=</span> <span class="p">(</span>
|
||||
<span class="n">all_</span> <span class="o">=</span> <span class="p">(</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">labels</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">place_names</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">streets</span>
|
||||
@@ -362,23 +377,23 @@
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">detected_text</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">city</span><span class="p">:</span>
|
||||
<span class="nb">all</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">city</span><span class="p">]</span>
|
||||
<span class="n">all_</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">city</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">state</span><span class="p">:</span>
|
||||
<span class="nb">all</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">state</span><span class="p">]</span>
|
||||
<span class="n">all_</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">state</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">state_abbreviation</span><span class="p">:</span>
|
||||
<span class="nb">all</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">state_abbreviation</span><span class="p">]</span>
|
||||
<span class="n">all_</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">state_abbreviation</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">country</span><span class="p">:</span>
|
||||
<span class="nb">all</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">country</span><span class="p">]</span>
|
||||
<span class="n">all_</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">country</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">month</span><span class="p">:</span>
|
||||
<span class="nb">all</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">month</span><span class="p">]</span>
|
||||
<span class="n">all_</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">month</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">year</span><span class="p">:</span>
|
||||
<span class="nb">all</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">year</span><span class="p">]</span>
|
||||
<span class="n">all_</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">year</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">season</span><span class="p">:</span>
|
||||
<span class="nb">all</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">season</span><span class="p">]</span>
|
||||
<span class="n">all_</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">season</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">camera</span><span class="p">:</span>
|
||||
<span class="nb">all</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">camera</span><span class="p">]</span>
|
||||
<span class="n">all_</span> <span class="o">+=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">camera</span><span class="p">]</span>
|
||||
|
||||
<span class="k">return</span> <span class="nb">all</span>
|
||||
<span class="k">return</span> <span class="n">all_</span>
|
||||
|
||||
<div class="viewcode-block" id="SearchInfo.asdict"><a class="viewcode-back" href="../../reference.html#osxphotos.SearchInfo.asdict">[docs]</a> <span class="k">def</span> <span class="nf">asdict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""return dict of search info"""</span>
|
||||
@@ -403,6 +418,7 @@
|
||||
<span class="s2">"media_types"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">media_types</span><span class="p">,</span>
|
||||
<span class="s2">"detected_text"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">detected_text</span><span class="p">,</span>
|
||||
<span class="s2">"camera"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">camera</span><span class="p">,</span>
|
||||
<span class="s2">"source"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">,</span>
|
||||
<span class="p">}</span></div>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_get_text_for_category</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">category</span><span class="p">):</span>
|
||||
|
||||
3282
docs/_sources/API_README.rst.txt
Normal file
3282
docs/_sources/API_README.rst.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,7 @@ Welcome to OSXPhotos's documentation!
|
||||
cli
|
||||
template_help
|
||||
package_overview
|
||||
api_readme
|
||||
reference
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
OSXPhotos python API
|
||||
====================
|
||||
OSXPhotos Python Reference
|
||||
==========================
|
||||
|
||||
.. automodule:: osxphotos
|
||||
:members:
|
||||
@@ -58,6 +58,8 @@ Valid filters are:
|
||||
* `join(x)`: Join list of values with delimiter x, e.g. join(,): ['a', 'b', 'c'] => 'a,b,c'; the DELIM option functions similar to join(x) but with DELIM, the join happens before being passed to any filters.May optionally be used without an argument, that is 'join()' which joins values together with no delimiter. e.g. join(): ['a', 'b', 'c'] => 'abc'.
|
||||
* `append(x)`: Append x to list of values, e.g. append(d): ['a', 'b', 'c'] => ['a', 'b', 'c', 'd'].
|
||||
* `prepend(x)`: Prepend x to list of values, e.g. prepend(d): ['a', 'b', 'c'] => ['d', 'a', 'b', 'c'].
|
||||
* `appends(x)`: Append s[tring] Append x to each value of list of values, e.g. appends(d): ['a', 'b', 'c'] => ['ad', 'bd', 'cd'].
|
||||
* `prepends(x)`: Prepend s[tring] x to each value of list of values, e.g. prepends(d): ['a', 'b', 'c'] => ['da', 'db', 'dc'].
|
||||
* `remove(x)`: Remove x from list of values, e.g. remove(b): ['a', 'b', 'c'] => ['a', 'c'].
|
||||
* `slice(start:stop:step)`: Slice list using same semantics as Python's list slicing, e.g. slice(1:3): ['a', 'b', 'c', 'd'] => ['b', 'c']; slice(1:4:2): ['a', 'b', 'c', 'd'] => ['b', 'd']; slice(1:): ['a', 'b', 'c', 'd'] => ['b', 'c', 'd']; slice(:-1): ['a', 'b', 'c', 'd'] => ['a', 'b', 'c']; slice(::-1): ['a', 'b', 'c', 'd'] => ['d', 'c', 'b', 'a']. See also sslice().
|
||||
* `sslice(start:stop:step)`: [s(tring) slice] Slice values in a list using same semantics as Python's string slicing, e.g. sslice(1:3):'abcd => 'bc'; sslice(1:4:2): 'abcd' => 'bd', etc. See also slice().
|
||||
@@ -160,9 +162,9 @@ e.g. ``"{created.year}/{openbrace}{title}{closebrace}"`` would result in ``"2020
|
||||
|
||||
**Variables**
|
||||
|
||||
You can define variables for later use in the template string using the format ``{var:NAME,VALUE}``. Variables may then be referenced using the format ``%NAME``. For example: ``{var:foo,bar}`` defines the variable ``%foo`` to have value ``bar``. This can be useful if you want to re-use a complex template value in multiple places within your template string or for allowing the use of characters that would otherwise be prohibited in a template string. For example, the "pipe" (\ ``|``\ ) character is not allowed in a find/replace pair but you can get around this limitation like so: ``{var:pipe,{pipe}}{title[-,%pipe]}`` which replaces the ``-`` character with ``|`` (the value of ``%pipe``\ ).
|
||||
You can define variables for later use in the template string using the format ``{var:NAME,VALUE}`` where ``VALUE`` is a template statement. Variables may then be referenced using the format ``%NAME``. For example: ``{var:foo,bar}`` defines the variable ``%foo`` to have value ``bar``. This can be useful if you want to re-use a complex template value in multiple places within your template string or for allowing the use of characters that would otherwise be prohibited in a template string. For example, the "pipe" (\ ``|``\ ) character is not allowed in a find/replace pair but you can get around this limitation like so: ``{var:pipe,{pipe}}{title[-,%pipe]}`` which replaces the ``-`` character with ``|`` (the value of ``%pipe``\ ).
|
||||
|
||||
Variables can also be referenced as fields in the template string, for example: ``{var:year,created.year}{original_name}-{%year}``. In some cases, use of variables can make your template string more readable. Variables can be used as template fields, as values for filters, as values for conditional operations, or as default values. When used as a conditional value or default value, variables should be treated like any other field and enclosed in braces as conditional and default values are evaluated as template strings. For example: ``{var:name,Katie}{person contains {%name}?{%name},Not-{%name}}``.
|
||||
Variables can also be referenced as fields in the template string, for example: ``{var:year,{created.year}}{original_name}-{%year}``. In some cases, use of variables can make your template string more readable. Variables can be used as template fields, as values for filters, as values for conditional operations, or as default values. When used as a conditional value or default value, variables should be treated like any other field and enclosed in braces as conditional and default values are evaluated as template strings. For example: ``{var:name,Katie}{person contains {%name}?{%name},Not-{%name}}``.
|
||||
|
||||
If you need to use a ``%`` (percent sign character), you can escape the percent sign by using ``%%``. You can also use the ``{percent}`` template field where a template field is required. For example:
|
||||
|
||||
@@ -322,6 +324,8 @@ Template Substitutions
|
||||
- A shorter representation of photo's internal universally unique identifier (UUID) for the photo, a 22-character string unique to the photo, e.g. 'JYsxugP9UjetmCbBCHXcmu'
|
||||
* - {id}
|
||||
- A unique number for the photo based on its primary key in the Photos database. A sequential integer, e.g. 1, 2, 3...etc. Each asset associated with a photo (e.g. an image and Live Photo preview) will share the same id. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{id:05d}' which results in 00001, 00002, 00003...etc.
|
||||
* - {counter}
|
||||
- A sequential counter, starting at 0, that increments each time it is evaluated.To start counting at a value other than 0, append append '(starting_value)' to the field name.For example, to start counting at 1 instead of 0: '{counter(1)}'.May be formatted using a python string format code.For example, to format as a 5-digit integer and pad with zeros, use '{counter:05d(1)}'which results in 00001, 00002, 00003...etc.You may also specify a stop value which causes the counter to reset to the starting valuewhen the stop value is reached and a step size which causes the counter to increment bythe specified value instead of 1. Use the format '{counter(start,stop,step)}' where start,stop, and step are integers. For example, to count from 1 to 10 by 2, use '{counter(1,11,2)}'.Note that the counter stops counting when the stop value is reached and does not return thestop value. Start, stop, and step are optional and may be omitted. For example, to countfrom 0 by 2s, use '{counter(,,2)}'.You may create an arbitrary number of counters by appending a unique name to the field namepreceded by a period: '{counter.a}', '{counter.b}', etc. Each counter will have its own stateand will start at 0 and increment by 1 unless otherwise specified. Note: {counter} is not suitable for use with 'export' and '--update' as the counter associated with a photo may change between export sessions. See also {id}.
|
||||
* - {album_seq}
|
||||
- An integer, starting at 0, indicating the photo's index (sequence) in the containing album. Only valid when used in a '--filename' template and only when '{album}' or '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{album\ *seq}*\ {original_name}"'. To start counting at a value other than 0, append append '(starting_value)' to the field name. For example, to start counting at 1 instead of 0: '{album_seq(1)}'. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{album_seq:05d}' which results in 00000, 00001, 00002...etc. To format while also using a starting value: '{album_seq:05d(1)}' which results in 0001, 00002...etc.This may result in incorrect sequences if you have duplicate albums with the same name; see also '{folder_album_seq}'.
|
||||
* - {folder_album_seq}
|
||||
@@ -357,7 +361,7 @@ Template Substitutions
|
||||
* - {tab}
|
||||
- :A tab: '\t'
|
||||
* - {osxphotos_version}
|
||||
- The osxphotos version, e.g. '0.56.2'
|
||||
- The osxphotos version, e.g. '0.61.0'
|
||||
* - {osxphotos_cmd_line}
|
||||
- The full command line used to run osxphotos
|
||||
* - {album}
|
||||
|
||||
3
docs/_static/copybutton.css
vendored
3
docs/_static/copybutton.css
vendored
@@ -35,7 +35,8 @@ div.highlight {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.highlight:hover button.copybtn {
|
||||
/* Show the copybutton */
|
||||
.highlight:hover button.copybtn, button.copybtn.success {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
42
docs/_static/copybutton.js
vendored
42
docs/_static/copybutton.js
vendored
@@ -102,18 +102,25 @@ const clearSelection = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// Changes tooltip text for two seconds, then changes it back
|
||||
// Changes tooltip text for a moment, then changes it back
|
||||
// We want the timeout of our `success` class to be a bit shorter than the
|
||||
// tooltip and icon change, so that we can hide the icon before changing back.
|
||||
var timeoutIcon = 2000;
|
||||
var timeoutSuccessClass = 1500;
|
||||
|
||||
const temporarilyChangeTooltip = (el, oldText, newText) => {
|
||||
el.setAttribute('data-tooltip', newText)
|
||||
el.classList.add('success')
|
||||
setTimeout(() => el.setAttribute('data-tooltip', oldText), 2000)
|
||||
setTimeout(() => el.classList.remove('success'), 2000)
|
||||
// Remove success a little bit sooner than we change the tooltip
|
||||
// So that we can use CSS to hide the copybutton first
|
||||
setTimeout(() => el.classList.remove('success'), timeoutSuccessClass)
|
||||
setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon)
|
||||
}
|
||||
|
||||
// Changes the copy button icon for two seconds, then changes it back
|
||||
const temporarilyChangeIcon = (el) => {
|
||||
el.innerHTML = iconCheck;
|
||||
setTimeout(() => {el.innerHTML = iconCopy}, 2000)
|
||||
setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon)
|
||||
}
|
||||
|
||||
const addCopyButtonToCodeCells = () => {
|
||||
@@ -125,7 +132,8 @@ const addCopyButtonToCodeCells = () => {
|
||||
}
|
||||
|
||||
// Add copybuttons to all of our code cells
|
||||
const codeCells = document.querySelectorAll('div.highlight pre')
|
||||
const COPYBUTTON_SELECTOR = 'div.highlight pre';
|
||||
const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR)
|
||||
codeCells.forEach((codeCell, index) => {
|
||||
const id = codeCellId(index)
|
||||
codeCell.setAttribute('id', id)
|
||||
@@ -141,10 +149,25 @@ function escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes excluded text from a Node.
|
||||
*
|
||||
* @param {Node} target Node to filter.
|
||||
* @param {string} exclude CSS selector of nodes to exclude.
|
||||
* @returns {DOMString} Text from `target` with text removed.
|
||||
*/
|
||||
function filterText(target, exclude) {
|
||||
const clone = target.cloneNode(true); // clone as to not modify the live DOM
|
||||
if (exclude) {
|
||||
// remove excluded nodes
|
||||
clone.querySelectorAll(exclude).forEach(node => node.remove());
|
||||
}
|
||||
return clone.innerText;
|
||||
}
|
||||
|
||||
// Callback when a copy button is clicked. Will be passed the node that was clicked
|
||||
// should then grab the text and replace pieces of text that shouldn't be used in output
|
||||
function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") {
|
||||
|
||||
var regexp;
|
||||
var match;
|
||||
|
||||
@@ -199,7 +222,12 @@ function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onl
|
||||
|
||||
var copyTargetText = (trigger) => {
|
||||
var target = document.querySelector(trigger.attributes['data-clipboard-target'].value);
|
||||
return formatCopyText(target.innerText, '', false, true, true, true, '', '')
|
||||
|
||||
// get filtered text
|
||||
let exclude = '.linenos, .gp';
|
||||
|
||||
let text = filterText(target, exclude);
|
||||
return formatCopyText(text, '', false, true, true, true, '', '')
|
||||
}
|
||||
|
||||
// Initialize with a callback so we can modify the text before copy
|
||||
|
||||
17
docs/_static/copybutton_funcs.js
vendored
17
docs/_static/copybutton_funcs.js
vendored
@@ -2,10 +2,25 @@ function escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes excluded text from a Node.
|
||||
*
|
||||
* @param {Node} target Node to filter.
|
||||
* @param {string} exclude CSS selector of nodes to exclude.
|
||||
* @returns {DOMString} Text from `target` with text removed.
|
||||
*/
|
||||
export function filterText(target, exclude) {
|
||||
const clone = target.cloneNode(true); // clone as to not modify the live DOM
|
||||
if (exclude) {
|
||||
// remove excluded nodes
|
||||
clone.querySelectorAll(exclude).forEach(node => node.remove());
|
||||
}
|
||||
return clone.innerText;
|
||||
}
|
||||
|
||||
// Callback when a copy button is clicked. Will be passed the node that was clicked
|
||||
// should then grab the text and replace pieces of text that shouldn't be used in output
|
||||
export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") {
|
||||
|
||||
var regexp;
|
||||
var match;
|
||||
|
||||
|
||||
2
docs/_static/documentation_options.js
vendored
2
docs/_static/documentation_options.js
vendored
@@ -1,6 +1,6 @@
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||
VERSION: '0.56.2',
|
||||
VERSION: '0.61.0',
|
||||
LANGUAGE: 'en',
|
||||
COLLAPSE_INDEX: false,
|
||||
BUILDER: 'html',
|
||||
|
||||
1284
docs/cli.html
1284
docs/cli.html
File diff suppressed because it is too large
Load Diff
1052
docs/genindex.html
1052
docs/genindex.html
File diff suppressed because it is too large
Load Diff
374
docs/index.html
374
docs/index.html
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos" href="overview.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos 0.56.2 documentation</title>
|
||||
<title>osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="#"><div class="brand">osxphotos 0.56.2 documentation</div></a>
|
||||
<a href="#"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="#">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.56.2 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -161,7 +161,8 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="api_readme.html">OSXPhotos Python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -236,7 +237,9 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="cli.html">OSXPhotos Command Line Interface (CLI)</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="cli.html#osxphotos">osxphotos</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-about">about</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-add-locations">add-locations</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-albums">albums</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-batch-edit">batch-edit</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-diff">diff</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-docs">docs</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-dump">dump</a></li>
|
||||
@@ -257,6 +260,7 @@
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-query">query</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-repl">repl</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-run">run</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-show">show</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-snap">snap</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-sync">sync</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="cli.html#osxphotos-theme">theme</a></li>
|
||||
@@ -279,8 +283,310 @@
|
||||
<li class="toctree-l2"><a class="reference internal" href="package_overview.html#using-the-osxphotos-cli-to-run-python-code">Using the osxphotos CLI to run python code</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos python API</a><ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="api_readme.html">OSXPhotos Python API</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="api_readme.html#table-of-contents">Table of Contents</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="api_readme.html#id1">Example uses of the Python package</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#print-filename-date-created-title-and-keywords-for-all-photos-in-a-library">Print filename, date created, title, and keywords for all photos in a library</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#building-simple-command-line-tools">Building simple command line tools</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="api_readme.html#concurrency">Concurrency</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="api_readme.html#id6">Package Interface</a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id7">PhotosDB</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#read-a-photos-library-database">Read a Photos library database</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#open-the-default-last-opened-photos-library">Open the default (last opened) Photos library</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#open-system-photos-library">Open System Photos library</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#open-a-specific-photos-library">Open a specific Photos library</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-photosdbphotos-photos-keywords-none-uuid-none-persons-none-albums-none-images-true-movies-true-from-date-none-to-date-none-intrash-false-a"><span class="raw-html-m2r"><A name="photosdbphotos"></span><code class="docutils literal notranslate"><span class="pre">photos(keywords=None,</span> <span class="pre">uuid=None,</span> <span class="pre">persons=None,</span> <span class="pre">albums=None,</span> <span class="pre">images=True,</span> <span class="pre">movies=True,</span> <span class="pre">from_date=None,</span> <span class="pre">to_date=None,</span> <span class="pre">intrash=False)</span></code></a></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-getphoto-get-photo-uuid-a"><span class="raw-html-m2r"><a name="getphoto"></span><code class="docutils literal notranslate"><span class="pre">get_photo(uuid)</span></code></A></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-photosdbquery-query-options-queryoptions-list-photoinfo-a"><span class="raw-html-m2r"><A name="photosdbquery"></span><code class="docutils literal notranslate"><span class="pre">query(options:</span> <span class="pre">QueryOptions)</span> <span class="pre">-></span> <span class="pre">List[PhotoInfo]:</span></code></a></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#keywords"><code class="docutils literal notranslate"><span class="pre">keywords</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-photosdbalbuminfo-album-info-a"><span class="raw-html-m2r"><a name="photosdbalbuminfo">`album_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id14"><code class="docutils literal notranslate"><span class="pre">albums</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#albums-shared"><code class="docutils literal notranslate"><span class="pre">albums_shared</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#import-info"><code class="docutils literal notranslate"><span class="pre">import_info</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#project-info"><code class="docutils literal notranslate"><span class="pre">project_info</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#moment-info"><code class="docutils literal notranslate"><span class="pre">moment_info</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#folder-info"><code class="docutils literal notranslate"><span class="pre">folder_info</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id19"><code class="docutils literal notranslate"><span class="pre">folders</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#persons"><code class="docutils literal notranslate"><span class="pre">persons</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-dbpersoninfo-person-info-a"><span class="raw-html-m2r"><a name="dbpersoninfo">`person_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#keywords-as-dict"><code class="docutils literal notranslate"><span class="pre">keywords_as_dict</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#persons-as-dict"><code class="docutils literal notranslate"><span class="pre">persons_as_dict</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#albums-as-dict"><code class="docutils literal notranslate"><span class="pre">albums_as_dict</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#albums-shared-as-dict"><code class="docutils literal notranslate"><span class="pre">albums_shared_as_dict</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#labels"><code class="docutils literal notranslate"><span class="pre">labels</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id22"><code class="docutils literal notranslate"><span class="pre">labels_normalized</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#labels-as-dict"><code class="docutils literal notranslate"><span class="pre">labels_as_dict</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id24"><code class="docutils literal notranslate"><span class="pre">labels_normalized_as_dict</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#library-path"><code class="docutils literal notranslate"><span class="pre">library_path</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#db-path"><code class="docutils literal notranslate"><span class="pre">db_path</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#db-version"><code class="docutils literal notranslate"><span class="pre">db_version</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#photos-version"><code class="docutils literal notranslate"><span class="pre">photos_version</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#get-db-connection"><code class="docutils literal notranslate"><span class="pre">get_db_connection()</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#execute-sql"><code class="docutils literal notranslate"><span class="pre">execute(sql)</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id26">QueryOptions</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#attributes">Attributes</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id27">PhotoInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#uuid"><code class="docutils literal notranslate"><span class="pre">uuid</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#filename"><code class="docutils literal notranslate"><span class="pre">filename</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id28"><code class="docutils literal notranslate"><span class="pre">original_filename</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#date"><code class="docutils literal notranslate"><span class="pre">date</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#date-added"><code class="docutils literal notranslate"><span class="pre">date_added</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#date-modified"><code class="docutils literal notranslate"><span class="pre">date_modified</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#description"><code class="docutils literal notranslate"><span class="pre">description</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#title"><code class="docutils literal notranslate"><span class="pre">title</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id30"><code class="docutils literal notranslate"><span class="pre">keywords</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id31"><code class="docutils literal notranslate"><span class="pre">albums</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id33"><code class="docutils literal notranslate"><span class="pre">album_info</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id36"><code class="docutils literal notranslate"><span class="pre">import_info</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id38"><code class="docutils literal notranslate"><span class="pre">project_info</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id40"><code class="docutils literal notranslate"><span class="pre">persons</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-photopersoninfo-person-info-a"><span class="raw-html-m2r"><a name="photopersoninfo">`person_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-photofaceinfo-face-info-a"><span class="raw-html-m2r"><a name="photofaceinfo">`face_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#path"><code class="docutils literal notranslate"><span class="pre">path</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#path-edited"><code class="docutils literal notranslate"><span class="pre">path_edited</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#path-derivatives"><code class="docutils literal notranslate"><span class="pre">path_derivatives</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#path-raw"><code class="docutils literal notranslate"><span class="pre">path_raw</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#has-raw"><code class="docutils literal notranslate"><span class="pre">has_raw</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#israw"><code class="docutils literal notranslate"><span class="pre">israw</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#raw-original"><code class="docutils literal notranslate"><span class="pre">raw_original</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#height"><code class="docutils literal notranslate"><span class="pre">height</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#width"><code class="docutils literal notranslate"><span class="pre">width</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#orientation"><code class="docutils literal notranslate"><span class="pre">orientation</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id48"><code class="docutils literal notranslate"><span class="pre">original_height</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id50"><code class="docutils literal notranslate"><span class="pre">original_width</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id52"><code class="docutils literal notranslate"><span class="pre">original_orientation</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#original-filesize"><code class="docutils literal notranslate"><span class="pre">original_filesize</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id54"><code class="docutils literal notranslate"><span class="pre">ismissing</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id56"><code class="docutils literal notranslate"><span class="pre">hasadjustments</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#adjustments"><code class="docutils literal notranslate"><span class="pre">adjustments</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#external-edit"><code class="docutils literal notranslate"><span class="pre">external_edit</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#favorite"><code class="docutils literal notranslate"><span class="pre">favorite</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id58"><code class="docutils literal notranslate"><span class="pre">hidden</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#visible"><code class="docutils literal notranslate"><span class="pre">visible</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#intrash"><code class="docutils literal notranslate"><span class="pre">intrash</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#date-trashed"><code class="docutils literal notranslate"><span class="pre">date_trashed</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#location"><code class="docutils literal notranslate"><span class="pre">location</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#place"><code class="docutils literal notranslate"><span class="pre">place</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id60"><code class="docutils literal notranslate"><span class="pre">shared</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#owner"><code class="docutils literal notranslate"><span class="pre">owner</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#comments"><code class="docutils literal notranslate"><span class="pre">comments</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#likes"><code class="docutils literal notranslate"><span class="pre">likes</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#isreference"><code class="docutils literal notranslate"><span class="pre">isreference</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#isphoto"><code class="docutils literal notranslate"><span class="pre">isphoto</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#ismovie"><code class="docutils literal notranslate"><span class="pre">ismovie</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#iscloudasset"><code class="docutils literal notranslate"><span class="pre">iscloudasset</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id71"><code class="docutils literal notranslate"><span class="pre">incloud</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#syndicated"><code class="docutils literal notranslate"><span class="pre">syndicated</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#saved-to-library"><code class="docutils literal notranslate"><span class="pre">saved_to_library</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#shared-moment"><code class="docutils literal notranslate"><span class="pre">shared_moment</span></code></a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#uti"><code class="docutils literal notranslate"><span class="pre">uti</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#uti-original"><code class="docutils literal notranslate"><span class="pre">uti_original</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#uti-edited"><code class="docutils literal notranslate"><span class="pre">uti_edited</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#uti-raw"><code class="docutils literal notranslate"><span class="pre">uti_raw</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id74"><code class="docutils literal notranslate"><span class="pre">burst</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#burst-selected"><code class="docutils literal notranslate"><span class="pre">burst_selected</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#burst-key"><code class="docutils literal notranslate"><span class="pre">burst_key</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#burst-default-pick"><code class="docutils literal notranslate"><span class="pre">burst_default_pick</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id75"><code class="docutils literal notranslate"><span class="pre">burst_photos</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id77"><code class="docutils literal notranslate"><span class="pre">burst_albums</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id80"><code class="docutils literal notranslate"><span class="pre">burst_album_info</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#live-photo"><code class="docutils literal notranslate"><span class="pre">live_photo</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id84"><code class="docutils literal notranslate"><span class="pre">path_live_photo</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#path-edited-live-photo"><code class="docutils literal notranslate"><span class="pre">path_edited_live_photo</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#portrait"><code class="docutils literal notranslate"><span class="pre">portrait</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#hdr"><code class="docutils literal notranslate"><span class="pre">hdr</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#selfie"><code class="docutils literal notranslate"><span class="pre">selfie</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#time-lapse"><code class="docutils literal notranslate"><span class="pre">time_lapse</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#panorama"><code class="docutils literal notranslate"><span class="pre">panorama</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#slow-mo"><code class="docutils literal notranslate"><span class="pre">slow_mo</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id88"><code class="docutils literal notranslate"><span class="pre">labels</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id90"><code class="docutils literal notranslate"><span class="pre">labels_normalized</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-photosearchinfo-search-info-a"><span class="raw-html-m2r"><a name="photosearchinfo">`search_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-photosearchinfo-normalized-search-info-normalized-a"><span class="raw-html-m2r"><a name="photosearchinfo-normalized">`search_info_normalized`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#exif-info"><code class="docutils literal notranslate"><span class="pre">exif_info</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id96"><code class="docutils literal notranslate"><span class="pre">exiftool</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#score"><code class="docutils literal notranslate"><span class="pre">score</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#duplicates"><code class="docutils literal notranslate"><span class="pre">duplicates</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#cloud-guid"><code class="docutils literal notranslate"><span class="pre">cloud_guid</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#cloud-owner-hashed-id"><code class="docutils literal notranslate"><span class="pre">cloud_owner_hashed_id</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#fingerprint"><code class="docutils literal notranslate"><span class="pre">fingerprint</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#hexdigest"><code class="docutils literal notranslate"><span class="pre">hexdigest</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#tables"><code class="docutils literal notranslate"><span class="pre">tables()</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#json"><code class="docutils literal notranslate"><span class="pre">json()</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#asdict"><code class="docutils literal notranslate"><span class="pre">asdict()</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#export"><code class="docutils literal notranslate"><span class="pre">export()</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-rendertemplate-render-template-template-str-options-none-a"><span class="raw-html-m2r"><a name="rendertemplate">`render_template(template_str, options=None)`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-detected-text-method-detected-text-confidence-threshold-text-detection-confidence-threshold-a"><span class="raw-html-m2r"><a name="detected_text_method">`detected_text(confidence_threshold=TEXT_DETECTION_CONFIDENCE_THRESHOLD)`</a></span></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id106">ExifInfo</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id107">AlbumInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id108"><code class="docutils literal notranslate"><span class="pre">uuid</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id109"><code class="docutils literal notranslate"><span class="pre">title</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-albumphotos-photos-a"><span class="raw-html-m2r"><a name="albumphotos">`photos`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#creation-date"><code class="docutils literal notranslate"><span class="pre">creation_date</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#start-date"><code class="docutils literal notranslate"><span class="pre">start_date</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#end-date"><code class="docutils literal notranslate"><span class="pre">end_date</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#folder-list"><code class="docutils literal notranslate"><span class="pre">folder_list</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#folder-names"><code class="docutils literal notranslate"><span class="pre">folder_names</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#parent"><code class="docutils literal notranslate"><span class="pre">parent</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id113"><code class="docutils literal notranslate"><span class="pre">owner</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id116"><code class="docutils literal notranslate"><span class="pre">asdict()</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id117">ImportInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id118"><code class="docutils literal notranslate"><span class="pre">uuid</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-importphotos-photos-a"><span class="raw-html-m2r"><a name="importphotos">`photos`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id120"><code class="docutils literal notranslate"><span class="pre">creation_date</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id121"><code class="docutils literal notranslate"><span class="pre">start_date</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id122"><code class="docutils literal notranslate"><span class="pre">end_date</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id123"><code class="docutils literal notranslate"><span class="pre">asdict()</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id124">ProjectInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id125"><code class="docutils literal notranslate"><span class="pre">uuid</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id126"><code class="docutils literal notranslate"><span class="pre">title</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-projectphotos-photos-a"><span class="raw-html-m2r"><a name="projectphotos">`photos`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id128"><code class="docutils literal notranslate"><span class="pre">creation_date</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id129"><code class="docutils literal notranslate"><span class="pre">asdict()</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id130">MomentInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#pk"><code class="docutils literal notranslate"><span class="pre">pk</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id131"><code class="docutils literal notranslate"><span class="pre">location</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id132"><code class="docutils literal notranslate"><span class="pre">title</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#subtitle"><code class="docutils literal notranslate"><span class="pre">subtitle</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id133"><code class="docutils literal notranslate"><span class="pre">start_date</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id134"><code class="docutils literal notranslate"><span class="pre">end_date</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id135"><code class="docutils literal notranslate"><span class="pre">date</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#modification-date"><code class="docutils literal notranslate"><span class="pre">modification_date</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id136"><code class="docutils literal notranslate"><span class="pre">photos</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id137"><code class="docutils literal notranslate"><span class="pre">asdict()</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id138">FolderInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id139"><code class="docutils literal notranslate"><span class="pre">uuid</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id140"><code class="docutils literal notranslate"><span class="pre">title</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id141"><code class="docutils literal notranslate"><span class="pre">album_info</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#album-info-shared"><code class="docutils literal notranslate"><span class="pre">album_info_shared</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#subfolders"><code class="docutils literal notranslate"><span class="pre">subfolders</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id145"><code class="docutils literal notranslate"><span class="pre">parent</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#sort-order"><code class="docutils literal notranslate"><span class="pre">sort_order</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#photo-index-photo"><code class="docutils literal notranslate"><span class="pre">photo_index(photo)</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id147"><code class="docutils literal notranslate"><span class="pre">asdict()</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id148">PlaceInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#ishome"><code class="docutils literal notranslate"><span class="pre">ishome</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#name"><code class="docutils literal notranslate"><span class="pre">name</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#names"><code class="docutils literal notranslate"><span class="pre">names</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#country-code"><code class="docutils literal notranslate"><span class="pre">country_code</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#address-str"><code class="docutils literal notranslate"><span class="pre">address_str</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#address"><code class="docutils literal notranslate"><span class="pre">address</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id149">ScoreInfo</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id150">SearchInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id151"><code class="docutils literal notranslate"><span class="pre">labels</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#place-names"><code class="docutils literal notranslate"><span class="pre">place_names</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#streets"><code class="docutils literal notranslate"><span class="pre">streets</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#neighborhoods"><code class="docutils literal notranslate"><span class="pre">neighborhoods</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#locality-names"><code class="docutils literal notranslate"><span class="pre">locality_names</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#city"><code class="docutils literal notranslate"><span class="pre">city</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#state"><code class="docutils literal notranslate"><span class="pre">state</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#state-abbreviation"><code class="docutils literal notranslate"><span class="pre">state_abbreviation</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#country"><code class="docutils literal notranslate"><span class="pre">country</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#month"><code class="docutils literal notranslate"><span class="pre">month</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#year"><code class="docutils literal notranslate"><span class="pre">year</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#bodies-of-water"><code class="docutils literal notranslate"><span class="pre">bodies_of_water</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#holidays"><code class="docutils literal notranslate"><span class="pre">holidays</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#activities"><code class="docutils literal notranslate"><span class="pre">activities</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#season"><code class="docutils literal notranslate"><span class="pre">season</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#venues"><code class="docutils literal notranslate"><span class="pre">venues</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#venue-types"><code class="docutils literal notranslate"><span class="pre">venue_types</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#media-types"><code class="docutils literal notranslate"><span class="pre">media_types</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#all"><code class="docutils literal notranslate"><span class="pre">all</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id152"><code class="docutils literal notranslate"><span class="pre">asdict()</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id153">PersonInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id154"><code class="docutils literal notranslate"><span class="pre">name</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#display-name"><code class="docutils literal notranslate"><span class="pre">display_name</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id155"><code class="docutils literal notranslate"><span class="pre">uuid</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#keyphoto"><code class="docutils literal notranslate"><span class="pre">keyphoto</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#facecount"><code class="docutils literal notranslate"><span class="pre">facecount</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-personphotos-photos-a"><span class="raw-html-m2r"><a name="personphotos">`photos`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-personfaceinfo-face-info-a"><span class="raw-html-m2r"><a name="personfaceinfo">`face_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-personfavorite-favorite-a"><span class="raw-html-m2r"><a name="personfavorite">`favorite`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#a-name-personsortorder-sort-order-a"><span class="raw-html-m2r"><a name="personsortorder">`sort_order`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id157"><code class="docutils literal notranslate"><span class="pre">json()</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id158"><code class="docutils literal notranslate"><span class="pre">asdict()</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id159">FaceInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id160"><code class="docutils literal notranslate"><span class="pre">uuid</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id161"><code class="docutils literal notranslate"><span class="pre">name</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#asset-uuid"><code class="docutils literal notranslate"><span class="pre">asset_uuid</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id162"><code class="docutils literal notranslate"><span class="pre">person_info</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#photo"><code class="docutils literal notranslate"><span class="pre">photo</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#mwg-rs-area"><code class="docutils literal notranslate"><span class="pre">mwg_rs_area</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#mpri-reg-rect"><code class="docutils literal notranslate"><span class="pre">mpri_reg_rect</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#face-rect"><code class="docutils literal notranslate"><span class="pre">face_rect()</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#center"><code class="docutils literal notranslate"><span class="pre">center</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#size-pixels"><code class="docutils literal notranslate"><span class="pre">size_pixels</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#roll-pitch-yaw"><code class="docutils literal notranslate"><span class="pre">roll_pitch_yaw()</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#roll">roll</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#pitch">pitch</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#yaw">yaw</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#additional-properties"><code class="docutils literal notranslate"><span class="pre">Additional</span> <span class="pre">properties</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id165"><code class="docutils literal notranslate"><span class="pre">asdict()</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id166"><code class="docutils literal notranslate"><span class="pre">json()</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id167">CommentInfo</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id168">LikeInfo</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id169">AdjustmentsInfo</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id170">PhotoTables</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id171">Raw Photos</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#raw-related-attributes">Raw-Related Attributes</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#example">Example</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id180">Template System</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#a-name-exiftoolexiftool-exiftool-a"><span class="raw-html-m2r"><a name="exiftoolExifTool">ExifTool</a></span></a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#exiftool-methods">ExifTool methods</a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#implementation-note">Implementation Note</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#a-name-photoexporter-photoexporter-a"><span class="raw-html-m2r"><a name="photoexporter">PhotoExporter</a></span></a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#export-dest-filename-none-options-optional-exportoptions-none-exportresults"><code class="docutils literal notranslate"><span class="pre">export(dest,</span> <span class="pre">filename=None,</span> <span class="pre">options:</span> <span class="pre">Optional[ExportOptions]=None)</span> <span class="pre">-></span> <span class="pre">ExportResults</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#exportoptions"><code class="docutils literal notranslate"><span class="pre">ExportOptions</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#exportresults"><code class="docutils literal notranslate"><span class="pre">ExportResults</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#a-name-textdetection-text-detection-a"><span class="raw-html-m2r"><a name="textdetection">Text Detection</a></span></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="api_readme.html#id183">Utility Functions</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id184"><code class="docutils literal notranslate"><span class="pre">get_system_library_path()</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#id185"><code class="docutils literal notranslate"><span class="pre">get_last_library_path()</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="api_readme.html#list-photo-libraries"><code class="docutils literal notranslate"><span class="pre">list_photo_libraries()</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="api_readme.html#id186">Additional Examples</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos Python Reference</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.AlbumInfo"><code class="docutils literal notranslate"><span class="pre">AlbumInfo</span></code></a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.AlbumInfo.asdict"><code class="docutils literal notranslate"><span class="pre">AlbumInfo.asdict()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.AlbumInfo.folder_list"><code class="docutils literal notranslate"><span class="pre">AlbumInfo.folder_list</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.AlbumInfo.folder_names"><code class="docutils literal notranslate"><span class="pre">AlbumInfo.folder_names</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.AlbumInfo.parent"><code class="docutils literal notranslate"><span class="pre">AlbumInfo.parent</span></code></a></li>
|
||||
@@ -305,6 +611,7 @@
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.ExportDB"><code class="docutils literal notranslate"><span class="pre">ExportDB</span></code></a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ExportDB.close"><code class="docutils literal notranslate"><span class="pre">ExportDB.close()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ExportDB.connection"><code class="docutils literal notranslate"><span class="pre">ExportDB.connection</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ExportDB.create_file_record"><code class="docutils literal notranslate"><span class="pre">ExportDB.create_file_record()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ExportDB.create_or_get_file_record"><code class="docutils literal notranslate"><span class="pre">ExportDB.create_or_get_file_record()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ExportDB.delete_data_for_filepath"><code class="docutils literal notranslate"><span class="pre">ExportDB.delete_data_for_filepath()</span></code></a></li>
|
||||
@@ -356,6 +663,7 @@
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ExportOptions.render_options"><code class="docutils literal notranslate"><span class="pre">ExportOptions.render_options</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ExportOptions.replace_keywords"><code class="docutils literal notranslate"><span class="pre">ExportOptions.replace_keywords</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ExportOptions.rich"><code class="docutils literal notranslate"><span class="pre">ExportOptions.rich</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ExportOptions.export_aae"><code class="docutils literal notranslate"><span class="pre">ExportOptions.export_aae</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ExportOptions.sidecar_drop_ext"><code class="docutils literal notranslate"><span class="pre">ExportOptions.sidecar_drop_ext</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ExportOptions.sidecar"><code class="docutils literal notranslate"><span class="pre">ExportOptions.sidecar</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ExportOptions.strip"><code class="docutils literal notranslate"><span class="pre">ExportOptions.strip</span></code></a></li>
|
||||
@@ -379,6 +687,22 @@
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ExportResults.datetime"><code class="docutils literal notranslate"><span class="pre">ExportResults.datetime</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.FaceInfo"><code class="docutils literal notranslate"><span class="pre">FaceInfo</span></code></a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FaceInfo.asdict"><code class="docutils literal notranslate"><span class="pre">FaceInfo.asdict()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FaceInfo.center"><code class="docutils literal notranslate"><span class="pre">FaceInfo.center</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FaceInfo.face_rect"><code class="docutils literal notranslate"><span class="pre">FaceInfo.face_rect()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FaceInfo.json"><code class="docutils literal notranslate"><span class="pre">FaceInfo.json()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FaceInfo.mpri_reg_rect"><code class="docutils literal notranslate"><span class="pre">FaceInfo.mpri_reg_rect</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FaceInfo.mwg_rs_area"><code class="docutils literal notranslate"><span class="pre">FaceInfo.mwg_rs_area</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FaceInfo.person_info"><code class="docutils literal notranslate"><span class="pre">FaceInfo.person_info</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FaceInfo.photo"><code class="docutils literal notranslate"><span class="pre">FaceInfo.photo</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FaceInfo.pitch"><code class="docutils literal notranslate"><span class="pre">FaceInfo.pitch</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FaceInfo.roll"><code class="docutils literal notranslate"><span class="pre">FaceInfo.roll</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FaceInfo.roll_pitch_yaw"><code class="docutils literal notranslate"><span class="pre">FaceInfo.roll_pitch_yaw()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FaceInfo.size_pixels"><code class="docutils literal notranslate"><span class="pre">FaceInfo.size_pixels</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FaceInfo.yaw"><code class="docutils literal notranslate"><span class="pre">FaceInfo.yaw</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.FileUtil"><code class="docutils literal notranslate"><span class="pre">FileUtil</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.FileUtilNoOp"><code class="docutils literal notranslate"><span class="pre">FileUtilNoOp</span></code></a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FileUtilNoOp.convert_to_jpeg"><code class="docutils literal notranslate"><span class="pre">FileUtilNoOp.convert_to_jpeg()</span></code></a></li>
|
||||
@@ -394,6 +718,7 @@
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.FolderInfo"><code class="docutils literal notranslate"><span class="pre">FolderInfo</span></code></a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FolderInfo.album_info"><code class="docutils literal notranslate"><span class="pre">FolderInfo.album_info</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FolderInfo.asdict"><code class="docutils literal notranslate"><span class="pre">FolderInfo.asdict()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FolderInfo.parent"><code class="docutils literal notranslate"><span class="pre">FolderInfo.parent</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FolderInfo.subfolders"><code class="docutils literal notranslate"><span class="pre">FolderInfo.subfolders</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.FolderInfo.title"><code class="docutils literal notranslate"><span class="pre">FolderInfo.title</span></code></a></li>
|
||||
@@ -401,7 +726,9 @@
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.ImportInfo"><code class="docutils literal notranslate"><span class="pre">ImportInfo</span></code></a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ImportInfo.asdict"><code class="docutils literal notranslate"><span class="pre">ImportInfo.asdict()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ImportInfo.photos"><code class="docutils literal notranslate"><span class="pre">ImportInfo.photos</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ImportInfo.title"><code class="docutils literal notranslate"><span class="pre">ImportInfo.title</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.LikeInfo"><code class="docutils literal notranslate"><span class="pre">LikeInfo</span></code></a></li>
|
||||
@@ -421,8 +748,11 @@
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.PersonInfo"><code class="docutils literal notranslate"><span class="pre">PersonInfo</span></code></a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.asdict"><code class="docutils literal notranslate"><span class="pre">PersonInfo.asdict()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.face_info"><code class="docutils literal notranslate"><span class="pre">PersonInfo.face_info</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.favorite"><code class="docutils literal notranslate"><span class="pre">PersonInfo.favorite</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.feature_less"><code class="docutils literal notranslate"><span class="pre">PersonInfo.feature_less</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.json"><code class="docutils literal notranslate"><span class="pre">PersonInfo.json()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.photos"><code class="docutils literal notranslate"><span class="pre">PersonInfo.photos</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PersonInfo.sort_order"><code class="docutils literal notranslate"><span class="pre">PersonInfo.sort_order</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.PhotoExporter"><code class="docutils literal notranslate"><span class="pre">PhotoExporter</span></code></a><ul>
|
||||
@@ -433,6 +763,7 @@
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo"><code class="docutils literal notranslate"><span class="pre">PhotoInfo</span></code></a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.adjustments"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.adjustments</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.adjustments_path"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.adjustments_path</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.album_info"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.album_info</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.albums"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.albums</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.asdict"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.asdict()</span></code></a></li>
|
||||
@@ -443,7 +774,9 @@
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.burst_key"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.burst_key</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.burst_photos"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.burst_photos</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.burst_selected"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.burst_selected</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.cloud_guid"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.cloud_guid</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.cloud_metadata"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.cloud_metadata</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.cloud_owner_hashed_id"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.cloud_owner_hashed_id</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.comments"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.comments</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.date"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.date</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.date_added"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.date_added</span></code></a></li>
|
||||
@@ -504,13 +837,17 @@
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.project_info"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.project_info</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.raw_original"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.raw_original</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.render_template"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.render_template()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.saved_to_library"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.saved_to_library</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.score"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.score</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.screenshot"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.screenshot</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.search_info"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.search_info</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.search_info_normalized"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.search_info_normalized</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.selfie"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.selfie</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.shared"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.shared</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.shared_moment"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.shared_moment</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.slow_mo"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.slow_mo</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.syndicated"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.syndicated</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.tables"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.tables()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.time_lapse"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.time_lapse</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.title"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.title</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.tzoffset"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.tzoffset</span></code></a></li>
|
||||
@@ -571,12 +908,26 @@
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotosDB.persons_as_dict"><code class="docutils literal notranslate"><span class="pre">PhotosDB.persons_as_dict</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotosDB.photos"><code class="docutils literal notranslate"><span class="pre">PhotosDB.photos()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotosDB.photos_by_uuid"><code class="docutils literal notranslate"><span class="pre">PhotosDB.photos_by_uuid()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotosDB.photos_version"><code class="docutils literal notranslate"><span class="pre">PhotosDB.photos_version</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotosDB.project_info"><code class="docutils literal notranslate"><span class="pre">PhotosDB.project_info</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotosDB.query"><code class="docutils literal notranslate"><span class="pre">PhotosDB.query()</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.PlaceInfo"><code class="docutils literal notranslate"><span class="pre">PlaceInfo</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.ProjectInfo"><code class="docutils literal notranslate"><span class="pre">ProjectInfo</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.PlaceInfo"><code class="docutils literal notranslate"><span class="pre">PlaceInfo</span></code></a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PlaceInfo.address"><code class="docutils literal notranslate"><span class="pre">PlaceInfo.address</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PlaceInfo.address_str"><code class="docutils literal notranslate"><span class="pre">PlaceInfo.address_str</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PlaceInfo.asdict"><code class="docutils literal notranslate"><span class="pre">PlaceInfo.asdict()</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PlaceInfo.country_code"><code class="docutils literal notranslate"><span class="pre">PlaceInfo.country_code</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PlaceInfo.ishome"><code class="docutils literal notranslate"><span class="pre">PlaceInfo.ishome</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PlaceInfo.name"><code class="docutils literal notranslate"><span class="pre">PlaceInfo.name</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PlaceInfo.names"><code class="docutils literal notranslate"><span class="pre">PlaceInfo.names</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.ProjectInfo"><code class="docutils literal notranslate"><span class="pre">ProjectInfo</span></code></a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ProjectInfo.folder_list"><code class="docutils literal notranslate"><span class="pre">ProjectInfo.folder_list</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.ProjectInfo.folder_names"><code class="docutils literal notranslate"><span class="pre">ProjectInfo.folder_names</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.QueryOptions"><code class="docutils literal notranslate"><span class="pre">QueryOptions</span></code></a><ul>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.added_after"><code class="docutils literal notranslate"><span class="pre">QueryOptions.added_after</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.added_before"><code class="docutils literal notranslate"><span class="pre">QueryOptions.added_before</span></code></a></li>
|
||||
@@ -624,6 +975,7 @@
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.no_title"><code class="docutils literal notranslate"><span class="pre">QueryOptions.no_title</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.not_burst"><code class="docutils literal notranslate"><span class="pre">QueryOptions.not_burst</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.not_cloudasset"><code class="docutils literal notranslate"><span class="pre">QueryOptions.not_cloudasset</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.not_edited"><code class="docutils literal notranslate"><span class="pre">QueryOptions.not_edited</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.not_favorite"><code class="docutils literal notranslate"><span class="pre">QueryOptions.not_favorite</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.not_hdr"><code class="docutils literal notranslate"><span class="pre">QueryOptions.not_hdr</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.not_hidden"><code class="docutils literal notranslate"><span class="pre">QueryOptions.not_hidden</span></code></a></li>
|
||||
@@ -657,6 +1009,12 @@
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.uti"><code class="docutils literal notranslate"><span class="pre">QueryOptions.uti</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.uuid"><code class="docutils literal notranslate"><span class="pre">QueryOptions.uuid</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.year"><code class="docutils literal notranslate"><span class="pre">QueryOptions.year</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.syndicated"><code class="docutils literal notranslate"><span class="pre">QueryOptions.syndicated</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.not_syndicated"><code class="docutils literal notranslate"><span class="pre">QueryOptions.not_syndicated</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.saved_to_library"><code class="docutils literal notranslate"><span class="pre">QueryOptions.saved_to_library</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.not_saved_to_library"><code class="docutils literal notranslate"><span class="pre">QueryOptions.not_saved_to_library</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.shared_moment"><code class="docutils literal notranslate"><span class="pre">QueryOptions.shared_moment</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.not_shared_moment"><code class="docutils literal notranslate"><span class="pre">QueryOptions.not_shared_moment</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="reference.html#osxphotos.ScoreInfo"><code class="docutils literal notranslate"><span class="pre">ScoreInfo</span></code></a><ul>
|
||||
@@ -680,9 +1038,11 @@
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.SearchInfo.neighborhoods"><code class="docutils literal notranslate"><span class="pre">SearchInfo.neighborhoods</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.SearchInfo.place_names"><code class="docutils literal notranslate"><span class="pre">SearchInfo.place_names</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.SearchInfo.season"><code class="docutils literal notranslate"><span class="pre">SearchInfo.season</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.SearchInfo.source"><code class="docutils literal notranslate"><span class="pre">SearchInfo.source</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.SearchInfo.state"><code class="docutils literal notranslate"><span class="pre">SearchInfo.state</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.SearchInfo.state_abbreviation"><code class="docutils literal notranslate"><span class="pre">SearchInfo.state_abbreviation</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.SearchInfo.streets"><code class="docutils literal notranslate"><span class="pre">SearchInfo.streets</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.SearchInfo.text_found"><code class="docutils literal notranslate"><span class="pre">SearchInfo.text_found</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.SearchInfo.venue_types"><code class="docutils literal notranslate"><span class="pre">SearchInfo.venue_types</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.SearchInfo.venues"><code class="docutils literal notranslate"><span class="pre">SearchInfo.venues</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.SearchInfo.year"><code class="docutils literal notranslate"><span class="pre">SearchInfo.year</span></code></a></li>
|
||||
|
||||
BIN
docs/objects.inv
BIN
docs/objects.inv
Binary file not shown.
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos Tutorial" href="tutorial.html" /><link rel="prev" title="Welcome to OSXPhotos’s documentation!" href="index.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>OSXPhotos - osxphotos 0.56.2 documentation</title>
|
||||
<title>OSXPhotos - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.56.2 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.56.2 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -161,7 +161,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<head><meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos python API" href="reference.html" /><link rel="prev" title="OSXPhotos Template System" href="template_help.html" />
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos Python Reference" href="reference.html" /><link rel="prev" title="OSXPhotos Template System" href="template_help.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>OSXPhotos Python Package Overview - osxphotos 0.56.2 documentation</title>
|
||||
<title>OSXPhotos Python Package Overview - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.56.2 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.56.2 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -161,7 +161,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1 current current-page"><a class="current reference internal" href="#">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -392,7 +392,7 @@ as well as <code class="docutils literal notranslate"><span class="pre">{functio
|
||||
<div class="context">
|
||||
<span>Next</span>
|
||||
</div>
|
||||
<div class="title">OSXPhotos python API</div>
|
||||
<div class="title">OSXPhotos Python Reference</div>
|
||||
</div>
|
||||
<svg class="furo-related-icon"><use href="#svg-arrow-right"></use></svg>
|
||||
</a>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Python Module Index - osxphotos 0.56.2 documentation</title>
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Python Module Index - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -122,7 +122,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.56.2 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -145,7 +145,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.56.2 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -159,7 +159,8 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="api_readme.html">OSXPhotos Python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="#" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Search - osxphotos 0.56.2 documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Search - osxphotos 0.61.0 documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||
@@ -121,7 +121,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.56.2 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -144,7 +144,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.56.2 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="#" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -158,7 +158,8 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="api_readme.html">OSXPhotos Python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos Python Package Overview" href="package_overview.html" /><link rel="prev" title="OSXPhotos Command Line Interface (CLI)" href="cli.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>OSXPhotos Template System - osxphotos 0.56.2 documentation</title>
|
||||
<title>OSXPhotos Template System - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.56.2 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.56.2 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -161,7 +161,8 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1 current current-page"><a class="current reference internal" href="#">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="api_readme.html">OSXPhotos Python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -240,6 +241,8 @@
|
||||
<li><p><cite>join(x)</cite>: Join list of values with delimiter x, e.g. join(,): [‘a’, ‘b’, ‘c’] => ‘a,b,c’; the DELIM option functions similar to join(x) but with DELIM, the join happens before being passed to any filters.May optionally be used without an argument, that is ‘join()’ which joins values together with no delimiter. e.g. join(): [‘a’, ‘b’, ‘c’] => ‘abc’.</p></li>
|
||||
<li><p><cite>append(x)</cite>: Append x to list of values, e.g. append(d): [‘a’, ‘b’, ‘c’] => [‘a’, ‘b’, ‘c’, ‘d’].</p></li>
|
||||
<li><p><cite>prepend(x)</cite>: Prepend x to list of values, e.g. prepend(d): [‘a’, ‘b’, ‘c’] => [‘d’, ‘a’, ‘b’, ‘c’].</p></li>
|
||||
<li><p><cite>appends(x)</cite>: Append s[tring] Append x to each value of list of values, e.g. appends(d): [‘a’, ‘b’, ‘c’] => [‘ad’, ‘bd’, ‘cd’].</p></li>
|
||||
<li><p><cite>prepends(x)</cite>: Prepend s[tring] x to each value of list of values, e.g. prepends(d): [‘a’, ‘b’, ‘c’] => [‘da’, ‘db’, ‘dc’].</p></li>
|
||||
<li><p><cite>remove(x)</cite>: Remove x from list of values, e.g. remove(b): [‘a’, ‘b’, ‘c’] => [‘a’, ‘c’].</p></li>
|
||||
<li><p><cite>slice(start:stop:step)</cite>: Slice list using same semantics as Python’s list slicing, e.g. slice(1:3): [‘a’, ‘b’, ‘c’, ‘d’] => [‘b’, ‘c’]; slice(1:4:2): [‘a’, ‘b’, ‘c’, ‘d’] => [‘b’, ‘d’]; slice(1:): [‘a’, ‘b’, ‘c’, ‘d’] => [‘b’, ‘c’, ‘d’]; slice(:-1): [‘a’, ‘b’, ‘c’, ‘d’] => [‘a’, ‘b’, ‘c’]; slice(::-1): [‘a’, ‘b’, ‘c’, ‘d’] => [‘d’, ‘c’, ‘b’, ‘a’]. See also sslice().</p></li>
|
||||
<li><p><cite>sslice(start:stop:step)</cite>: [s(tring) slice] Slice values in a list using same semantics as Python’s string slicing, e.g. sslice(1:3):’abcd => ‘bc’; sslice(1:4:2): ‘abcd’ => ‘bd’, etc. See also slice().</p></li>
|
||||
@@ -318,8 +321,8 @@
|
||||
<p>If you want to include “{” or “}” in the output, use “{openbrace}” or “{closebrace}” template substitution.</p>
|
||||
<p>e.g. <code class="docutils literal notranslate"><span class="pre">"{created.year}/{openbrace}{title}{closebrace}"</span></code> would result in <code class="docutils literal notranslate"><span class="pre">"2020/{Photo</span> <span class="pre">Title}"</span></code>.</p>
|
||||
<p><strong>Variables</strong></p>
|
||||
<p>You can define variables for later use in the template string using the format <code class="docutils literal notranslate"><span class="pre">{var:NAME,VALUE}</span></code>. Variables may then be referenced using the format <code class="docutils literal notranslate"><span class="pre">%NAME</span></code>. For example: <code class="docutils literal notranslate"><span class="pre">{var:foo,bar}</span></code> defines the variable <code class="docutils literal notranslate"><span class="pre">%foo</span></code> to have value <code class="docutils literal notranslate"><span class="pre">bar</span></code>. This can be useful if you want to re-use a complex template value in multiple places within your template string or for allowing the use of characters that would otherwise be prohibited in a template string. For example, the “pipe” (<code class="docutils literal notranslate"><span class="pre">|</span></code>) character is not allowed in a find/replace pair but you can get around this limitation like so: <code class="docutils literal notranslate"><span class="pre">{var:pipe,{pipe}}{title[-,%pipe]}</span></code> which replaces the <code class="docutils literal notranslate"><span class="pre">-</span></code> character with <code class="docutils literal notranslate"><span class="pre">|</span></code> (the value of <code class="docutils literal notranslate"><span class="pre">%pipe</span></code>).</p>
|
||||
<p>Variables can also be referenced as fields in the template string, for example: <code class="docutils literal notranslate"><span class="pre">{var:year,created.year}{original_name}-{%year}</span></code>. In some cases, use of variables can make your template string more readable. Variables can be used as template fields, as values for filters, as values for conditional operations, or as default values. When used as a conditional value or default value, variables should be treated like any other field and enclosed in braces as conditional and default values are evaluated as template strings. For example: <code class="docutils literal notranslate"><span class="pre">{var:name,Katie}{person</span> <span class="pre">contains</span> <span class="pre">{%name}?{%name},Not-{%name}}</span></code>.</p>
|
||||
<p>You can define variables for later use in the template string using the format <code class="docutils literal notranslate"><span class="pre">{var:NAME,VALUE}</span></code> where <code class="docutils literal notranslate"><span class="pre">VALUE</span></code> is a template statement. Variables may then be referenced using the format <code class="docutils literal notranslate"><span class="pre">%NAME</span></code>. For example: <code class="docutils literal notranslate"><span class="pre">{var:foo,bar}</span></code> defines the variable <code class="docutils literal notranslate"><span class="pre">%foo</span></code> to have value <code class="docutils literal notranslate"><span class="pre">bar</span></code>. This can be useful if you want to re-use a complex template value in multiple places within your template string or for allowing the use of characters that would otherwise be prohibited in a template string. For example, the “pipe” (<code class="docutils literal notranslate"><span class="pre">|</span></code>) character is not allowed in a find/replace pair but you can get around this limitation like so: <code class="docutils literal notranslate"><span class="pre">{var:pipe,{pipe}}{title[-,%pipe]}</span></code> which replaces the <code class="docutils literal notranslate"><span class="pre">-</span></code> character with <code class="docutils literal notranslate"><span class="pre">|</span></code> (the value of <code class="docutils literal notranslate"><span class="pre">%pipe</span></code>).</p>
|
||||
<p>Variables can also be referenced as fields in the template string, for example: <code class="docutils literal notranslate"><span class="pre">{var:year,{created.year}}{original_name}-{%year}</span></code>. In some cases, use of variables can make your template string more readable. Variables can be used as template fields, as values for filters, as values for conditional operations, or as default values. When used as a conditional value or default value, variables should be treated like any other field and enclosed in braces as conditional and default values are evaluated as template strings. For example: <code class="docutils literal notranslate"><span class="pre">{var:name,Katie}{person</span> <span class="pre">contains</span> <span class="pre">{%name}?{%name},Not-{%name}}</span></code>.</p>
|
||||
<p>If you need to use a <code class="docutils literal notranslate"><span class="pre">%</span></code> (percent sign character), you can escape the percent sign by using <code class="docutils literal notranslate"><span class="pre">%%</span></code>. You can also use the <code class="docutils literal notranslate"><span class="pre">{percent}</span></code> template field where a template field is required. For example:</p>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">{title[:,%%]}</span></code> replaces the <code class="docutils literal notranslate"><span class="pre">:</span></code> with <code class="docutils literal notranslate"><span class="pre">%</span></code> and <code class="docutils literal notranslate"><span class="pre">{title</span> <span class="pre">contains</span> <span class="pre">Foo?{title}{percent},{title}}</span></code> adds <code class="docutils literal notranslate"><span class="pre">%</span></code> to the title if it contains <code class="docutils literal notranslate"><span class="pre">Foo</span></code>.</p>
|
||||
<section id="id1">
|
||||
@@ -551,55 +554,58 @@
|
||||
<tr class="row-even"><td><p>{id}</p></td>
|
||||
<td><p>A unique number for the photo based on its primary key in the Photos database. A sequential integer, e.g. 1, 2, 3…etc. Each asset associated with a photo (e.g. an image and Live Photo preview) will share the same id. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use ‘{id:05d}’ which results in 00001, 00002, 00003…etc.</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{album_seq}</p></td>
|
||||
<tr class="row-odd"><td><p>{counter}</p></td>
|
||||
<td><p>A sequential counter, starting at 0, that increments each time it is evaluated.To start counting at a value other than 0, append append ‘(starting_value)’ to the field name.For example, to start counting at 1 instead of 0: ‘{counter(1)}’.May be formatted using a python string format code.For example, to format as a 5-digit integer and pad with zeros, use ‘{counter:05d(1)}’which results in 00001, 00002, 00003…etc.You may also specify a stop value which causes the counter to reset to the starting valuewhen the stop value is reached and a step size which causes the counter to increment bythe specified value instead of 1. Use the format ‘{counter(start,stop,step)}’ where start,stop, and step are integers. For example, to count from 1 to 10 by 2, use ‘{counter(1,11,2)}’.Note that the counter stops counting when the stop value is reached and does not return thestop value. Start, stop, and step are optional and may be omitted. For example, to countfrom 0 by 2s, use ‘{counter(,,2)}’.You may create an arbitrary number of counters by appending a unique name to the field namepreceded by a period: ‘{counter.a}’, ‘{counter.b}’, etc. Each counter will have its own stateand will start at 0 and increment by 1 unless otherwise specified. Note: {counter} is not suitable for use with ‘export’ and ‘–update’ as the counter associated with a photo may change between export sessions. See also {id}.</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{album_seq}</p></td>
|
||||
<td><p>An integer, starting at 0, indicating the photo’s index (sequence) in the containing album. Only valid when used in a ‘–filename’ template and only when ‘{album}’ or ‘{folder_album}’ is used in the ‘–directory’ template. For example ‘–directory “{folder_album}” –filename “{album<em>seq}</em>{original_name}”’. To start counting at a value other than 0, append append ‘(starting_value)’ to the field name. For example, to start counting at 1 instead of 0: ‘{album_seq(1)}’. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use ‘{album_seq:05d}’ which results in 00000, 00001, 00002…etc. To format while also using a starting value: ‘{album_seq:05d(1)}’ which results in 0001, 00002…etc.This may result in incorrect sequences if you have duplicate albums with the same name; see also ‘{folder_album_seq}’.</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{folder_album_seq}</p></td>
|
||||
<tr class="row-odd"><td><p>{folder_album_seq}</p></td>
|
||||
<td><p>An integer, starting at 0, indicating the photo’s index (sequence) in the containing album and folder path. Only valid when used in a ‘–filename’ template and only when ‘{folder_album}’ is used in the ‘–directory’ template. For example ‘–directory “{folder_album}” –filename “{folder_album<em>seq}</em>{original_name}”’. To start counting at a value other than 0, append ‘(starting_value)’ to the field name. For example, to start counting at 1 instead of 0: ‘{folder_album_seq(1)}’ May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use ‘{folder_album_seq:05d}’ which results in 00000, 00001, 00002…etc. To format while also using a starting value: ‘{folder_album_seq:05d(1)}’ which results in 0001, 00002…etc.This may result in incorrect sequences if you have duplicate albums with the same name in the same folder; see also ‘{album_seq}’.</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{comma}</p></td>
|
||||
<tr class="row-even"><td><p>{comma}</p></td>
|
||||
<td><p>A comma: ‘,’</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{semicolon}</p></td>
|
||||
<tr class="row-odd"><td><p>{semicolon}</p></td>
|
||||
<td><p>A semicolon: ‘;’</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{questionmark}</p></td>
|
||||
<tr class="row-even"><td><p>{questionmark}</p></td>
|
||||
<td><p>A question mark: ‘?’</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{pipe}</p></td>
|
||||
<tr class="row-odd"><td><p>{pipe}</p></td>
|
||||
<td><p>A vertical pipe: ‘|’</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{openbrace}</p></td>
|
||||
<tr class="row-even"><td><p>{openbrace}</p></td>
|
||||
<td><p>An open brace: ‘{’</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{closebrace}</p></td>
|
||||
<tr class="row-odd"><td><p>{closebrace}</p></td>
|
||||
<td><p>A close brace: ‘}’</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{openparens}</p></td>
|
||||
<tr class="row-even"><td><p>{openparens}</p></td>
|
||||
<td><p>An open parentheses: ‘(’</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{closeparens}</p></td>
|
||||
<tr class="row-odd"><td><p>{closeparens}</p></td>
|
||||
<td><p>A close parentheses: ‘)’</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{openbracket}</p></td>
|
||||
<tr class="row-even"><td><p>{openbracket}</p></td>
|
||||
<td><p>An open bracket: ‘[’</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{closebracket}</p></td>
|
||||
<tr class="row-odd"><td><p>{closebracket}</p></td>
|
||||
<td><p>A close bracket: ‘]’</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{newline}</p></td>
|
||||
<tr class="row-even"><td><p>{newline}</p></td>
|
||||
<td><p>A newline: ‘n’</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{lf}</p></td>
|
||||
<tr class="row-odd"><td><p>{lf}</p></td>
|
||||
<td><p>A line feed: ‘n’, alias for {newline}</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{cr}</p></td>
|
||||
<tr class="row-even"><td><p>{cr}</p></td>
|
||||
<td><p>A carriage return: ‘r’</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{crlf}</p></td>
|
||||
<tr class="row-odd"><td><p>{crlf}</p></td>
|
||||
<td><p>A carriage return + line feed: ‘rn’</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{tab}</p></td>
|
||||
<tr class="row-even"><td><p>{tab}</p></td>
|
||||
<td><dl class="field-list simple">
|
||||
<dt class="field-odd">A tab<span class="colon">:</span></dt>
|
||||
<dd class="field-odd"><p>‘t’</p>
|
||||
@@ -607,73 +613,73 @@
|
||||
</dl>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{osxphotos_version}</p></td>
|
||||
<td><p>The osxphotos version, e.g. ‘0.56.2’</p></td>
|
||||
<tr class="row-odd"><td><p>{osxphotos_version}</p></td>
|
||||
<td><p>The osxphotos version, e.g. ‘0.61.0’</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{osxphotos_cmd_line}</p></td>
|
||||
<tr class="row-even"><td><p>{osxphotos_cmd_line}</p></td>
|
||||
<td><p>The full command line used to run osxphotos</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{album}</p></td>
|
||||
<tr class="row-odd"><td><p>{album}</p></td>
|
||||
<td><p>Album(s) photo is contained in</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{folder_album}</p></td>
|
||||
<tr class="row-even"><td><p>{folder_album}</p></td>
|
||||
<td><p>Folder path + album photo is contained in. e.g. ‘Folder/Subfolder/Album’ or just ‘Album’ if no enclosing folder</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{project}</p></td>
|
||||
<tr class="row-odd"><td><p>{project}</p></td>
|
||||
<td><p>Project(s) photo is contained in (such as greeting cards, calendars, slideshows)</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{album_project}</p></td>
|
||||
<tr class="row-even"><td><p>{album_project}</p></td>
|
||||
<td><p>Album(s) and project(s) photo is contained in; treats projects as regular albums</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{folder_album_project}</p></td>
|
||||
<tr class="row-odd"><td><p>{folder_album_project}</p></td>
|
||||
<td><p>Folder path + album (includes projects as albums) photo is contained in. e.g. ‘Folder/Subfolder/Album’ or just ‘Album’ if no enclosing folder</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{keyword}</p></td>
|
||||
<tr class="row-even"><td><p>{keyword}</p></td>
|
||||
<td><p>Keyword(s) assigned to photo</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{person}</p></td>
|
||||
<tr class="row-odd"><td><p>{person}</p></td>
|
||||
<td><p>Person(s) / face(s) in a photo</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{label}</p></td>
|
||||
<tr class="row-even"><td><p>{label}</p></td>
|
||||
<td><p>Image categorization label associated with a photo (Photos 5+ only). Labels are added automatically by Photos using machine learning algorithms to categorize images. These are not the same as {keyword} which refers to the user-defined keywords/tags applied in Photos.</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{label_normalized}</p></td>
|
||||
<tr class="row-odd"><td><p>{label_normalized}</p></td>
|
||||
<td><p>All lower case version of ‘label’ (Photos 5+ only)</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{comment}</p></td>
|
||||
<tr class="row-even"><td><p>{comment}</p></td>
|
||||
<td><p>Comment(s) on shared Photos; format is ‘Person name: comment text’ (Photos 5+ only)</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{exiftool}</p></td>
|
||||
<tr class="row-odd"><td><p>{exiftool}</p></td>
|
||||
<td><p>Format: ‘{exiftool:GROUP:TAGNAME}’; use exiftool (https://exiftool.org) to extract metadata, in form GROUP:TAGNAME, from image. E.g. ‘{exiftool:EXIF:Make}’ to get camera make, or {exiftool:IPTC:Keywords} to extract keywords. See https://exiftool.org/TagNames/ for list of valid tag names. You must specify group (e.g. EXIF, IPTC, etc) as used in <code class="docutils literal notranslate"><span class="pre">exiftool</span> <span class="pre">-G</span></code>. exiftool must be installed in the path to use this template.</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{searchinfo.holiday}</p></td>
|
||||
<tr class="row-even"><td><p>{searchinfo.holiday}</p></td>
|
||||
<td><p>Holiday names associated with a photo, e.g. ‘Christmas Day’; (Photos 5+ only, applied automatically by Photos’ image categorization algorithms).</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{searchinfo.activity}</p></td>
|
||||
<tr class="row-odd"><td><p>{searchinfo.activity}</p></td>
|
||||
<td><p>Activities associated with a photo, e.g. ‘Sporting Event’; (Photos 5+ only, applied automatically by Photos’ image categorization algorithms).</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{searchinfo.venue}</p></td>
|
||||
<tr class="row-even"><td><p>{searchinfo.venue}</p></td>
|
||||
<td><p>Venues associated with a photo, e.g. name of restaurant; (Photos 5+ only, applied automatically by Photos’ image categorization algorithms).</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{searchinfo.venue_type}</p></td>
|
||||
<tr class="row-odd"><td><p>{searchinfo.venue_type}</p></td>
|
||||
<td><p>Venue types associated with a photo, e.g. ‘Restaurant’; (Photos 5+ only, applied automatically by Photos’ image categorization algorithms).</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{photo}</p></td>
|
||||
<tr class="row-even"><td><p>{photo}</p></td>
|
||||
<td><p>Provides direct access to the PhotoInfo object for the photo. Must be used in format ‘{photo.property}’ where ‘property’ represents a PhotoInfo property. For example: ‘{photo.favorite}’ is the same as ‘{favorite}’ and ‘{photo.place.name}’ is the same as ‘{place.name}’. ‘{photo}’ provides access to properties that are not available as separate template fields but it assumes some knowledge of the underlying PhotoInfo class. See <a class="reference external" href="https://rhettbull.github.io/osxphotos/">https://rhettbull.github.io/osxphotos/</a> for additional documentation on the PhotoInfo class.</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{detected_text}</p></td>
|
||||
<tr class="row-odd"><td><p>{detected_text}</p></td>
|
||||
<td><p>List of text strings found in the image after performing text detection. Using ‘{detected_text}’ will cause osxphotos to perform text detection on your photos using the built-in macOS text detection algorithms which will slow down your export. The results for each photo will be cached in the export database so that future exports with ‘–update’ do not need to reprocess each photo. You may pass a confidence threshold value between 0.0 and 1.0 after a colon as in ‘{detected_text:0.5}’; The default confidence threshold is 0.75. ‘{detected_text}’ works only on macOS Catalina (10.15) or later. Note: this feature is not the same thing as Live Text in macOS Monterey, which osxphotos does not yet support.</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{shell_quote}</p></td>
|
||||
<tr class="row-even"><td><p>{shell_quote}</p></td>
|
||||
<td><p>Use in form ‘{shell_quote,TEMPLATE}’; quotes the rendered TEMPLATE value(s) for safe usage in the shell, e.g. My file.jpeg => ‘My file.jpeg’; only adds quotes if needed.</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{strip}</p></td>
|
||||
<tr class="row-odd"><td><p>{strip}</p></td>
|
||||
<td><p>Use in form ‘{strip,TEMPLATE}’; strips whitespace from begining and end of rendered TEMPLATE value(s).</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{format}</p></td>
|
||||
<tr class="row-even"><td><p>{format}</p></td>
|
||||
<td><p>Use in form, ‘{format:TYPE:FORMAT,TEMPLATE}’; converts TEMPLATE value to TYPE then formats the value using Python string formatting codes specified by FORMAT; TYPE is one of: ‘int’, ‘float’, or ‘str’. For example, ‘{format:float:.1f,{exiftool:EXIF:FocalLength}}’ will format focal length to 1 decimal place (e.g. ‘100.0’).</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{function}</p></td>
|
||||
<tr class="row-odd"><td><p>{function}</p></td>
|
||||
<td><p>Execute a python function from an external file and use return value as template substitution. Use in format: {function:file.py::function_name} where ‘file.py’ is the name of the python file and ‘function_name’ is the name of the function to call. The function will be passed the PhotoInfo object for the photo. See https://github.com/RhetTbull/osxphotos/blob/master/examples/template_function.py for an example of how to implement a template function.</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos Command Line Interface (CLI)" href="cli.html" /><link rel="prev" title="OSXPhotos" href="overview.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>OSXPhotos Tutorial - osxphotos 0.56.2 documentation</title>
|
||||
<title>OSXPhotos Tutorial - osxphotos 0.61.0 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.56.2 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.61.0 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.56.2 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.61.0 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -161,7 +161,8 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="template_help.html">OSXPhotos Template System</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="package_overview.html">OSXPhotos Python Package Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="api_readme.html">OSXPhotos Python API</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="reference.html">OSXPhotos Python Reference</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
3282
docsrc/source/api_readme.rst
Normal file
3282
docsrc/source/api_readme.rst
Normal file
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,7 @@ Welcome to OSXPhotos's documentation!
|
||||
cli
|
||||
template_help
|
||||
package_overview
|
||||
api_readme
|
||||
reference
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
OSXPhotos python API
|
||||
====================
|
||||
OSXPhotos Python Reference
|
||||
==========================
|
||||
|
||||
.. automodule:: osxphotos
|
||||
:members:
|
||||
@@ -58,6 +58,8 @@ Valid filters are:
|
||||
* `join(x)`: Join list of values with delimiter x, e.g. join(,): ['a', 'b', 'c'] => 'a,b,c'; the DELIM option functions similar to join(x) but with DELIM, the join happens before being passed to any filters.May optionally be used without an argument, that is 'join()' which joins values together with no delimiter. e.g. join(): ['a', 'b', 'c'] => 'abc'.
|
||||
* `append(x)`: Append x to list of values, e.g. append(d): ['a', 'b', 'c'] => ['a', 'b', 'c', 'd'].
|
||||
* `prepend(x)`: Prepend x to list of values, e.g. prepend(d): ['a', 'b', 'c'] => ['d', 'a', 'b', 'c'].
|
||||
* `appends(x)`: Append s[tring] Append x to each value of list of values, e.g. appends(d): ['a', 'b', 'c'] => ['ad', 'bd', 'cd'].
|
||||
* `prepends(x)`: Prepend s[tring] x to each value of list of values, e.g. prepends(d): ['a', 'b', 'c'] => ['da', 'db', 'dc'].
|
||||
* `remove(x)`: Remove x from list of values, e.g. remove(b): ['a', 'b', 'c'] => ['a', 'c'].
|
||||
* `slice(start:stop:step)`: Slice list using same semantics as Python's list slicing, e.g. slice(1:3): ['a', 'b', 'c', 'd'] => ['b', 'c']; slice(1:4:2): ['a', 'b', 'c', 'd'] => ['b', 'd']; slice(1:): ['a', 'b', 'c', 'd'] => ['b', 'c', 'd']; slice(:-1): ['a', 'b', 'c', 'd'] => ['a', 'b', 'c']; slice(::-1): ['a', 'b', 'c', 'd'] => ['d', 'c', 'b', 'a']. See also sslice().
|
||||
* `sslice(start:stop:step)`: [s(tring) slice] Slice values in a list using same semantics as Python's string slicing, e.g. sslice(1:3):'abcd => 'bc'; sslice(1:4:2): 'abcd' => 'bd', etc. See also slice().
|
||||
@@ -160,9 +162,9 @@ e.g. ``"{created.year}/{openbrace}{title}{closebrace}"`` would result in ``"2020
|
||||
|
||||
**Variables**
|
||||
|
||||
You can define variables for later use in the template string using the format ``{var:NAME,VALUE}``. Variables may then be referenced using the format ``%NAME``. For example: ``{var:foo,bar}`` defines the variable ``%foo`` to have value ``bar``. This can be useful if you want to re-use a complex template value in multiple places within your template string or for allowing the use of characters that would otherwise be prohibited in a template string. For example, the "pipe" (\ ``|``\ ) character is not allowed in a find/replace pair but you can get around this limitation like so: ``{var:pipe,{pipe}}{title[-,%pipe]}`` which replaces the ``-`` character with ``|`` (the value of ``%pipe``\ ).
|
||||
You can define variables for later use in the template string using the format ``{var:NAME,VALUE}`` where ``VALUE`` is a template statement. Variables may then be referenced using the format ``%NAME``. For example: ``{var:foo,bar}`` defines the variable ``%foo`` to have value ``bar``. This can be useful if you want to re-use a complex template value in multiple places within your template string or for allowing the use of characters that would otherwise be prohibited in a template string. For example, the "pipe" (\ ``|``\ ) character is not allowed in a find/replace pair but you can get around this limitation like so: ``{var:pipe,{pipe}}{title[-,%pipe]}`` which replaces the ``-`` character with ``|`` (the value of ``%pipe``\ ).
|
||||
|
||||
Variables can also be referenced as fields in the template string, for example: ``{var:year,created.year}{original_name}-{%year}``. In some cases, use of variables can make your template string more readable. Variables can be used as template fields, as values for filters, as values for conditional operations, or as default values. When used as a conditional value or default value, variables should be treated like any other field and enclosed in braces as conditional and default values are evaluated as template strings. For example: ``{var:name,Katie}{person contains {%name}?{%name},Not-{%name}}``.
|
||||
Variables can also be referenced as fields in the template string, for example: ``{var:year,{created.year}}{original_name}-{%year}``. In some cases, use of variables can make your template string more readable. Variables can be used as template fields, as values for filters, as values for conditional operations, or as default values. When used as a conditional value or default value, variables should be treated like any other field and enclosed in braces as conditional and default values are evaluated as template strings. For example: ``{var:name,Katie}{person contains {%name}?{%name},Not-{%name}}``.
|
||||
|
||||
If you need to use a ``%`` (percent sign character), you can escape the percent sign by using ``%%``. You can also use the ``{percent}`` template field where a template field is required. For example:
|
||||
|
||||
@@ -322,6 +324,8 @@ Template Substitutions
|
||||
- A shorter representation of photo's internal universally unique identifier (UUID) for the photo, a 22-character string unique to the photo, e.g. 'JYsxugP9UjetmCbBCHXcmu'
|
||||
* - {id}
|
||||
- A unique number for the photo based on its primary key in the Photos database. A sequential integer, e.g. 1, 2, 3...etc. Each asset associated with a photo (e.g. an image and Live Photo preview) will share the same id. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{id:05d}' which results in 00001, 00002, 00003...etc.
|
||||
* - {counter}
|
||||
- A sequential counter, starting at 0, that increments each time it is evaluated.To start counting at a value other than 0, append append '(starting_value)' to the field name.For example, to start counting at 1 instead of 0: '{counter(1)}'.May be formatted using a python string format code.For example, to format as a 5-digit integer and pad with zeros, use '{counter:05d(1)}'which results in 00001, 00002, 00003...etc.You may also specify a stop value which causes the counter to reset to the starting valuewhen the stop value is reached and a step size which causes the counter to increment bythe specified value instead of 1. Use the format '{counter(start,stop,step)}' where start,stop, and step are integers. For example, to count from 1 to 10 by 2, use '{counter(1,11,2)}'.Note that the counter stops counting when the stop value is reached and does not return thestop value. Start, stop, and step are optional and may be omitted. For example, to countfrom 0 by 2s, use '{counter(,,2)}'.You may create an arbitrary number of counters by appending a unique name to the field namepreceded by a period: '{counter.a}', '{counter.b}', etc. Each counter will have its own stateand will start at 0 and increment by 1 unless otherwise specified. Note: {counter} is not suitable for use with 'export' and '--update' as the counter associated with a photo may change between export sessions. See also {id}.
|
||||
* - {album_seq}
|
||||
- An integer, starting at 0, indicating the photo's index (sequence) in the containing album. Only valid when used in a '--filename' template and only when '{album}' or '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{album\ *seq}*\ {original_name}"'. To start counting at a value other than 0, append append '(starting_value)' to the field name. For example, to start counting at 1 instead of 0: '{album_seq(1)}'. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{album_seq:05d}' which results in 00000, 00001, 00002...etc. To format while also using a starting value: '{album_seq:05d(1)}' which results in 0001, 00002...etc.This may result in incorrect sequences if you have duplicate albums with the same name; see also '{folder_album_seq}'.
|
||||
* - {folder_album_seq}
|
||||
@@ -357,7 +361,7 @@ Template Substitutions
|
||||
* - {tab}
|
||||
- :A tab: '\t'
|
||||
* - {osxphotos_version}
|
||||
- The osxphotos version, e.g. '0.56.2'
|
||||
- The osxphotos version, e.g. '0.61.0'
|
||||
* - {osxphotos_cmd_line}
|
||||
- The full command line used to run osxphotos
|
||||
* - {album}
|
||||
|
||||
325
examples/batch_edit.py
Normal file
325
examples/batch_edit.py
Normal file
@@ -0,0 +1,325 @@
|
||||
"""
|
||||
Batch edit currently selected photo metadata using osxphotos.
|
||||
|
||||
Run this with `osxphotos run batch_edit.py` or `osxphotos run batch_edit.py --help` for more information.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import functools
|
||||
import json
|
||||
import sys
|
||||
|
||||
import click
|
||||
import photoscript
|
||||
|
||||
import osxphotos
|
||||
from osxphotos.cli import echo, echo_error, kvstore, selection_command, verbose
|
||||
from osxphotos.cli.param_types import TemplateString
|
||||
from osxphotos.phototemplate import RenderOptions
|
||||
from osxphotos.sqlitekvstore import SQLiteKVStore
|
||||
|
||||
|
||||
class Latitude(click.ParamType):
|
||||
name = "Latitude"
|
||||
|
||||
def convert(self, value, param, ctx):
|
||||
try:
|
||||
latitude = float(value)
|
||||
if latitude < -90 or latitude > 90:
|
||||
raise ValueError
|
||||
return latitude
|
||||
except Exception:
|
||||
self.fail(
|
||||
f"Invalid latitude {value}. Must be a floating point number between -90 and 90."
|
||||
)
|
||||
|
||||
|
||||
class Longitude(click.ParamType):
|
||||
name = "Longitude"
|
||||
|
||||
def convert(self, value, param, ctx):
|
||||
try:
|
||||
longitude = float(value)
|
||||
if longitude < -180 or longitude > 180:
|
||||
raise ValueError
|
||||
return longitude
|
||||
except Exception:
|
||||
self.fail(
|
||||
f"Invalid longitude {value}. Must be a floating point number between -180 and 180."
|
||||
)
|
||||
|
||||
|
||||
@selection_command(name="batch-edit")
|
||||
@click.option(
|
||||
"--title",
|
||||
metavar="TITLE_TEMPLATE",
|
||||
type=TemplateString(),
|
||||
help="Set title of photo.",
|
||||
)
|
||||
@click.option(
|
||||
"--description",
|
||||
metavar="DESCRIPTION_TEMPLATE",
|
||||
type=TemplateString(),
|
||||
help="Set description of photo.",
|
||||
)
|
||||
@click.option(
|
||||
"--keyword",
|
||||
metavar="KEYWORD_TEMPLATE",
|
||||
type=TemplateString(),
|
||||
multiple=True,
|
||||
help="Set keywords of photo. May be specified multiple times.",
|
||||
)
|
||||
@click.option(
|
||||
"--location",
|
||||
metavar="LATITUDE LONGITUDE",
|
||||
type=click.Tuple([Latitude(), Longitude()]),
|
||||
help="Set location of photo. "
|
||||
"Must be specified as a pair of numbers with latitude in the range -90 to 90 and longitude in the range -180 to 180.",
|
||||
)
|
||||
@click.option("--dry-run", is_flag=True, help="Don't actually change anything.")
|
||||
@click.option(
|
||||
"--undo",
|
||||
is_flag=True,
|
||||
help="Restores photo metadata to what it was prior to the last batch edit. "
|
||||
"May be combined with --dry-run.",
|
||||
)
|
||||
def batch_edit(
|
||||
photos: list[osxphotos.PhotoInfo],
|
||||
title,
|
||||
description,
|
||||
keyword,
|
||||
location,
|
||||
dry_run,
|
||||
undo,
|
||||
**kwargs,
|
||||
):
|
||||
"""
|
||||
Batch edit photo metadata such as title, description, keywords, etc.
|
||||
Operates on currently selected photos.
|
||||
|
||||
Select one or more photos in Photos then run this command to edit the metadata.
|
||||
|
||||
For example:
|
||||
|
||||
\b
|
||||
osxphotos run batch_edit.py \\
|
||||
--verbose \\
|
||||
--title "California vacation 2023 {created.year}-{created.dd}-{created.mm} {counter:03d}" \\
|
||||
--description "{place.name}" \\
|
||||
--keyword "Family" --keyword "Travel" --keyword "{keyword}"
|
||||
|
||||
This will set the title to "California vacation 2023 2023-02-20 001", and so on,
|
||||
the description to the reverse geolocation place name,
|
||||
and the keywords to "Family", "Travel", and any existing keywords of the photo.
|
||||
|
||||
--title, --description, and --keyword may be any valid template string.
|
||||
See https://rhettbull.github.io/osxphotos/template_help.html for more information
|
||||
on the osxphotos template system.
|
||||
"""
|
||||
|
||||
if not title and not description and not keyword and not location and not undo:
|
||||
echo_error(
|
||||
"[error] Must specify at least one of: "
|
||||
" --title, --description, --keyword, --location, --undo. "
|
||||
"Use --help for more information."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
if undo and (title or description or keyword or location):
|
||||
echo_error(
|
||||
"[error] Cannot specify --undo and any options other than --dry-run. "
|
||||
"Use --help for more information."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
if not photos:
|
||||
echo_error("[error] No photos selected")
|
||||
sys.exit(1)
|
||||
|
||||
# sort photos by date so that {counter} order is correct
|
||||
photos.sort(key=lambda p: p.date)
|
||||
|
||||
undo_store = kvstore("batch_edit")
|
||||
verbose(f"Undo database stored in [filepath]{undo_store.path}", level=2)
|
||||
|
||||
echo(f"Processing [num]{len(photos)}[/] photos...")
|
||||
for photo in photos:
|
||||
verbose(
|
||||
f"Processing [filename]{photo.original_filename}[/] ([uuid]{photo.uuid}[/])"
|
||||
)
|
||||
if undo:
|
||||
undo_photo_edits(photo, undo_store, dry_run)
|
||||
continue
|
||||
save_photo_undo_info(undo_store, photo)
|
||||
set_photo_title_from_template(photo, title, dry_run)
|
||||
set_photo_description_from_template(photo, description, dry_run)
|
||||
set_photo_keywords_from_template(photo, keyword, dry_run)
|
||||
set_photo_location(photo, location, dry_run)
|
||||
|
||||
|
||||
# cache photoscript Photo object to avoid re-creating it for each photo
|
||||
# maxsize=1 as this function is called repeatedly for each photo then
|
||||
# the next photo is processed
|
||||
@functools.lru_cache(maxsize=1)
|
||||
def photoscript_photo(photo: osxphotos.PhotoInfo) -> photoscript.Photo:
|
||||
"""Return photoscript Photo object for photo"""
|
||||
return photoscript.Photo(photo.uuid)
|
||||
|
||||
|
||||
def save_photo_undo_info(undo_store: SQLiteKVStore, photo: osxphotos.PhotoInfo):
|
||||
"""Save undo information to undo store"""
|
||||
undo_store[photo.uuid] = photo.json()
|
||||
|
||||
|
||||
def undo_photo_edits(
|
||||
photo: osxphotos.PhotoInfo, undo_store: SQLiteKVStore, dry_run: bool
|
||||
):
|
||||
"""Undo edits for photo"""
|
||||
if not (undo_info := undo_store.get(photo.uuid)):
|
||||
verbose(
|
||||
f"[warning] No undo information for photo [filename]{photo.original_filename}[/] ([uuid]{photo.uuid}[/])"
|
||||
)
|
||||
return
|
||||
undo_info = json.loads(undo_info)
|
||||
ps_photo = photoscript_photo(photo)
|
||||
exiting_title, exiting_description, exiting_keywords, exiting_location = (
|
||||
photo.title,
|
||||
photo.description,
|
||||
sorted(photo.keywords),
|
||||
photo.location,
|
||||
)
|
||||
previous_title, previous_description, previous_keywords, previous_location = (
|
||||
undo_info.get("title"),
|
||||
undo_info.get("description"),
|
||||
sorted(undo_info.get("keywords")),
|
||||
(undo_info.get("latitude"), undo_info.get("longitude")),
|
||||
)
|
||||
verbose(
|
||||
f"Undoing edits for [filename]{photo.original_filename}[/] ([uuid]{photo.uuid}[/])"
|
||||
)
|
||||
for name, existing, previous in (
|
||||
("title", exiting_title, previous_title),
|
||||
("description", exiting_description, previous_description),
|
||||
("keywords", exiting_keywords, previous_keywords),
|
||||
("location", exiting_location, previous_location),
|
||||
):
|
||||
if existing != previous:
|
||||
verbose(
|
||||
f" [i]{name}[/]: [change]{existing}[/] -> [no_change]{previous}[/]"
|
||||
)
|
||||
if not dry_run:
|
||||
setattr(ps_photo, name, previous)
|
||||
else:
|
||||
verbose(f" [i]{name} (no change)[/]: [no_change]{existing}[/]", level=2)
|
||||
|
||||
|
||||
def set_photo_title_from_template(
|
||||
photo: osxphotos.PhotoInfo, title_template: str, dry_run: bool
|
||||
):
|
||||
"""Set photo title from template"""
|
||||
if not title_template:
|
||||
return
|
||||
|
||||
# don't render None values
|
||||
render_options = RenderOptions(none_str="")
|
||||
|
||||
title_string, _ = photo.render_template(title_template, render_options)
|
||||
title_string = [ts for ts in title_string if ts]
|
||||
if not title_string:
|
||||
verbose(
|
||||
f"No title returned from template, nothing to do: [bold]{title_template}"
|
||||
)
|
||||
return
|
||||
|
||||
if len(title_string) > 1:
|
||||
echo_error(
|
||||
f"[error] Title template must return a single string: [bold]{title_string}"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
verbose(f"Setting [i]title[/i] to [bold]{title_string[0]}")
|
||||
if not dry_run:
|
||||
ps_photo = photoscript_photo(photo)
|
||||
ps_photo.title = title_string[0]
|
||||
|
||||
|
||||
def set_photo_description_from_template(
|
||||
photo: osxphotos.PhotoInfo, description_template: str, dry_run: bool
|
||||
):
|
||||
"""Set photo description from template"""
|
||||
if not description_template:
|
||||
return
|
||||
|
||||
# don't render None values
|
||||
render_options = RenderOptions(none_str="")
|
||||
|
||||
description_string, _ = photo.render_template(description_template, render_options)
|
||||
description_string = [ds for ds in description_string if ds]
|
||||
if not description_string:
|
||||
verbose(
|
||||
f"No description returned from template, nothing to do: [bold]{description_template}"
|
||||
)
|
||||
return
|
||||
|
||||
if len(description_string) > 1:
|
||||
echo_error(
|
||||
f"[error] Description template must return a single string: [bold]{description_string}"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
verbose(f"Setting [i]description[/] to [bold]{description_string[0]}")
|
||||
if not dry_run:
|
||||
ps_photo = photoscript_photo(photo)
|
||||
ps_photo.description = description_string[0]
|
||||
|
||||
|
||||
def set_photo_keywords_from_template(
|
||||
photo: osxphotos.PhotoInfo, keyword_template: list[str], dry_run: bool
|
||||
):
|
||||
"""Set photo keywords from template"""
|
||||
if not keyword_template:
|
||||
return
|
||||
|
||||
# don't render None values
|
||||
render_options = RenderOptions(none_str="")
|
||||
|
||||
keywords = set()
|
||||
for kw in keyword_template:
|
||||
kw_string, _ = photo.render_template(kw, render_options)
|
||||
if kw_string:
|
||||
# filter out empty strings
|
||||
keywords.update([k for k in kw_string if k])
|
||||
|
||||
if not keywords:
|
||||
verbose(
|
||||
f"No keywords returned from template, nothing to do: [bold]{keyword_template}"
|
||||
)
|
||||
return
|
||||
|
||||
verbose(
|
||||
f"Setting [i]keywords[/] to {', '.join(f'[bold]{kw}[/]' for kw in keywords)}"
|
||||
)
|
||||
if not dry_run:
|
||||
ps_photo = photoscript_photo(photo)
|
||||
ps_photo.keywords = list(keywords)
|
||||
|
||||
|
||||
def set_photo_location(
|
||||
photo: osxphotos.PhotoInfo, location: tuple[float, float], dry_run: bool
|
||||
):
|
||||
"""Set photo location"""
|
||||
if not location or location[0] is None or location[1] is None:
|
||||
return
|
||||
|
||||
latitude, longitude = location
|
||||
verbose(
|
||||
f"Setting [i]location[/] to [num]{latitude:.6f}[/], [num]{longitude:.6f}[/]"
|
||||
)
|
||||
if not dry_run:
|
||||
ps_photo = photoscript_photo(photo)
|
||||
ps_photo.location = (latitude, longitude)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
batch_edit()
|
||||
67
examples/cli_example_1.py
Normal file
67
examples/cli_example_1.py
Normal file
@@ -0,0 +1,67 @@
|
||||
"""Sample query command for osxphotos
|
||||
|
||||
This shows how simple it is to create a command line tool using osxphotos to process your photos.
|
||||
|
||||
Using the @query_command decorator turns your function to a full-fledged command line app that
|
||||
can be run via `osxphotos run cli_example_1.py` or `python cli_example_1.py` if you have pip installed osxphotos.
|
||||
|
||||
Using this decorator makes it very easy to create a quick command line tool that can operate on
|
||||
a subset of your photos. Additionally, writing a command in this way makes it easy to later
|
||||
incorporate the command into osxphotos as a full-fledged command.
|
||||
|
||||
The decorator will add all the query options available in `osxphotos query` as command line options
|
||||
as well as the following options:
|
||||
--verbose
|
||||
--timestamp
|
||||
--theme
|
||||
--db
|
||||
--debug (hidden, won't show in help)
|
||||
|
||||
The decorated function will perform the query and pass the list of filtered PhotoInfo objects
|
||||
to your function. You can then do whatever you want with the photos.
|
||||
|
||||
For example, to run the command on only selected photos:
|
||||
|
||||
osxphotos run cli_example_1.py --selected
|
||||
|
||||
To run the command on all photos with the keyword "foo":
|
||||
|
||||
osxphotos run cli_example_1.py --keyword foo
|
||||
|
||||
For more advanced example, see `cli_example_2.py`
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import osxphotos
|
||||
from osxphotos.cli import query_command, verbose
|
||||
|
||||
|
||||
@query_command
|
||||
def example(photos: list[osxphotos.PhotoInfo], **kwargs):
|
||||
"""Sample query command for osxphotos. Prints out the filename and date of each photo.
|
||||
|
||||
Whatever text you put in the function's docstring here, will be used as the command's
|
||||
help text when run via `osxphotos run cli_example_1.py --help` or `python cli_example_1.py --help`
|
||||
"""
|
||||
|
||||
# verbose() will print to stdout if --verbose option is set
|
||||
# you can optionally provide a level (default is 1) to print only if --verbose is set to that level
|
||||
# for example: -VV or --verbose --verbose == level 2
|
||||
verbose(f"Found {len(photos)} photo(s)")
|
||||
verbose("This message will only be printed if verbose level 2 is set", level=2)
|
||||
|
||||
# do something with photos here
|
||||
for photo in photos:
|
||||
# photos is a list of PhotoInfo objects
|
||||
# see: https://rhettbull.github.io/osxphotos/reference.html#osxphotos.PhotoInfo
|
||||
verbose(f"Processing {photo.original_filename}")
|
||||
print(f"{photo.original_filename} {photo.date}")
|
||||
...
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# call your function here
|
||||
# you do not need to pass any arguments to the function
|
||||
# as the decorator will handle parsing the command line arguments
|
||||
example()
|
||||
160
examples/cli_example_2.py
Normal file
160
examples/cli_example_2.py
Normal file
@@ -0,0 +1,160 @@
|
||||
"""Sample query command for osxphotos
|
||||
|
||||
This shows how simple it is to create a command line tool using osxphotos to process your photos.
|
||||
|
||||
Using the @query_command decorator turns your function to a full-fledged command line app that
|
||||
can be run via `osxphotos run cli_example_2.py` or `python cli_example_2.py` if you have pip installed osxphotos.
|
||||
|
||||
Using this decorator makes it very easy to create a quick command line tool that can operate on
|
||||
a subset of your photos. Additionally, writing a command in this way makes it easy to later
|
||||
incorporate the command into osxphotos as a full-fledged command.
|
||||
|
||||
The decorator will add all the query options available in `osxphotos query` as command line options
|
||||
as well as the following options:
|
||||
--verbose
|
||||
--timestamp
|
||||
--theme
|
||||
--db
|
||||
--debug (hidden, won't show in help)
|
||||
|
||||
The decorated function will perform the query and pass the list of filtered PhotoInfo objects
|
||||
to your function. You can then do whatever you want with the photos.
|
||||
|
||||
For example, to run the command on only selected photos:
|
||||
|
||||
osxphotos run cli_example_2.py --selected
|
||||
|
||||
To run the command on all photos with the keyword "foo":
|
||||
|
||||
osxphotos run cli_example_2.py --keyword foo
|
||||
|
||||
The following helper functions may be useful and can be imported from osxphotos.cli:
|
||||
|
||||
abort(message: str, exit_code: int = 1)
|
||||
Abort with error message and exit code
|
||||
echo(message: str)
|
||||
Print message to stdout using rich formatting
|
||||
echo_error(message: str)
|
||||
Print message to stderr using rich formatting
|
||||
logger: logging.Logger
|
||||
Python logger for osxphotos; for example, logger.debug("debug message")
|
||||
verbose(*args, level: int = 1)
|
||||
Print args to stdout if --verbose option is set
|
||||
query_command: decorator to create an osxphotos query command
|
||||
kvstore(name: str) -> SQLiteKVStore useful for storing state between runs
|
||||
|
||||
The verbose, echo, and echo_error functions use rich formatting to print messages to stdout and stderr.
|
||||
See https://github.com/Textualize/rich for more information on rich formatting.
|
||||
|
||||
In addition to standard rich formatting styles, the following styles will be defined
|
||||
(and can be changed using --theme):
|
||||
|
||||
[change]: something change
|
||||
[no_change]: indicate no change
|
||||
[count]: a count
|
||||
[error]: an error
|
||||
[filename]: a filename
|
||||
[filepath]: a filepath
|
||||
[num]: a number
|
||||
[time]: a time or date
|
||||
[tz]: a timezone
|
||||
[warning]: a warning
|
||||
[uuid]: a uuid
|
||||
|
||||
The tags should be closed with [/] to end the style. For example:
|
||||
|
||||
echo("[filename]foo[/] [time]bar[/]")
|
||||
|
||||
For simpler examples, see `cli_example_1.py`
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
|
||||
import click
|
||||
|
||||
import osxphotos
|
||||
from osxphotos.cli import (
|
||||
abort,
|
||||
echo,
|
||||
echo_error,
|
||||
kvstore,
|
||||
logger,
|
||||
query_command,
|
||||
verbose,
|
||||
)
|
||||
|
||||
|
||||
@query_command()
|
||||
@click.option(
|
||||
"--resume",
|
||||
is_flag=True,
|
||||
help="Resume processing from last run, do not reprocess photos",
|
||||
)
|
||||
@click.option(
|
||||
"--dry-run", is_flag=True, help="Do a dry run, don't actually do anything"
|
||||
)
|
||||
def example(resume, dry_run, photos: list[osxphotos.PhotoInfo], **kwargs):
|
||||
"""Sample query command for osxphotos. Prints out the filename and date of each photo.
|
||||
|
||||
Whatever text you put in the function's docstring here, will be used as the command's
|
||||
help text when run via `osxphotos run cli_example_2.py --help` or `python cli_example_2.py --help`
|
||||
|
||||
The @query_command decorator returns a click.command so you can add additional options
|
||||
using standard click decorators. For example, the --resume and --dry-run options.
|
||||
For more information on click, see https://palletsprojects.com/p/click/.
|
||||
"""
|
||||
|
||||
# abort will print the message to stderr and exit with the given exit code
|
||||
if not photos:
|
||||
abort("Nothing to do!", 1)
|
||||
|
||||
# verbose() will print to stdout if --verbose option is set
|
||||
# you can optionally provide a level (default is 1) to print only if --verbose is set to that level
|
||||
# for example: -VV or --verbose --verbose == level 2
|
||||
verbose(f"Found [count]{len(photos)}[/] photos")
|
||||
verbose("This message will only be printed if verbose level 2 is set", level=2)
|
||||
|
||||
# the logger is a python logging.Logger object
|
||||
# debug messages will only be printed if --debug option is set
|
||||
logger.debug(f"{kwargs=}")
|
||||
|
||||
# kvstore() returns a SQLiteKVStore object for storing state between runs
|
||||
# this is basically a persistent dictionary that can be used to store state
|
||||
# see https://github.com/RhetTbull/sqlitekvstore for more information
|
||||
kv = kvstore("cli_example_2")
|
||||
verbose(f"Using key-value cache: {kv.path}")
|
||||
|
||||
# do something with photos here
|
||||
for photo in photos:
|
||||
# photos is a list of PhotoInfo objects
|
||||
# see: https://rhettbull.github.io/osxphotos/reference.html#osxphotos.PhotoInfo
|
||||
if resume and photo.uuid in kv:
|
||||
echo(
|
||||
f"Skipping processed photo [filename]{photo.original_filename}[/] ([uuid]{photo.uuid}[/])"
|
||||
)
|
||||
continue
|
||||
|
||||
# store the uuid and current time in the kvstore
|
||||
# the key and value must be a type supported by SQLite: int, float, str, bytes, bool, None
|
||||
# if you need to store other values, you should serialize them to a string or bytes first
|
||||
# for example, using json.dumps() or pickle.dumps()
|
||||
kv[photo.uuid] = datetime.datetime.now().isoformat()
|
||||
echo(f"Processing [filename]{photo.original_filename}[/] [time]{photo.date}[/]")
|
||||
if not dry_run:
|
||||
# do something with the photo here
|
||||
echo(f"Doing something with [filename]{photo.original_filename}[/]")
|
||||
|
||||
# echo_error will print to stderr
|
||||
# if you add [warning] or [error], it will be formatted accordingly
|
||||
# and include an emoji to make the message stand out
|
||||
echo_error("[warning]This is a warning message!")
|
||||
echo_error("[error]This is an error message!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# call your function here
|
||||
# you do not need to pass any arguments to the function
|
||||
# as the decorator will handle parsing the command line arguments
|
||||
example()
|
||||
57
examples/cli_example_3.py
Normal file
57
examples/cli_example_3.py
Normal file
@@ -0,0 +1,57 @@
|
||||
"""Sample query command for osxphotos
|
||||
|
||||
This shows how simple it is to create a command line tool using osxphotos to process your photos.
|
||||
|
||||
Using the @selection_command decorator turns your function to a full-fledged command line app that
|
||||
can be run via `osxphotos run cli_example_1.py` or `python cli_example_1.py` if you have pip installed osxphotos.
|
||||
|
||||
Using this decorator makes it very easy to create a quick command line tool that can operate on
|
||||
a subset of your photos. Additionally, writing a command in this way makes it easy to later
|
||||
incorporate the command into osxphotos as a full-fledged command.
|
||||
|
||||
The decorator will add the following options to your command:
|
||||
--verbose
|
||||
--timestamp
|
||||
--theme
|
||||
--db
|
||||
--debug (hidden, won't show in help)
|
||||
|
||||
The decorated function will get the selected photos and pass the list of PhotoInfo objects
|
||||
to your function. You can then do whatever you want with the photos.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import osxphotos
|
||||
from osxphotos.cli import selection_command, verbose
|
||||
|
||||
|
||||
@selection_command
|
||||
def example(photos: list[osxphotos.PhotoInfo], **kwargs):
|
||||
"""Sample command for osxphotos. Prints out the filename and date of each photo
|
||||
currently selected in Photos.app.
|
||||
|
||||
Whatever text you put in the function's docstring here, will be used as the command's
|
||||
help text when run via `osxphotos run cli_example_1.py --help` or `python cli_example_1.py --help`
|
||||
"""
|
||||
|
||||
# verbose() will print to stdout if --verbose option is set
|
||||
# you can optionally provide a level (default is 1) to print only if --verbose is set to that level
|
||||
# for example: -VV or --verbose --verbose == level 2
|
||||
verbose(f"Found {len(photos)} photo(s)")
|
||||
verbose("This message will only be printed if verbose level 2 is set", level=2)
|
||||
|
||||
# do something with photos here
|
||||
for photo in photos:
|
||||
# photos is a list of PhotoInfo objects
|
||||
# see: https://rhettbull.github.io/osxphotos/reference.html#osxphotos.PhotoInfo
|
||||
verbose(f"Processing {photo.original_filename}")
|
||||
print(f"{photo.original_filename} {photo.date}")
|
||||
...
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# call your function here
|
||||
# you do not need to pass any arguments to the function
|
||||
# as the decorator will handle parsing the command line arguments
|
||||
example()
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
import sys
|
||||
|
||||
import osxphotos
|
||||
import click
|
||||
|
||||
import osxphotos
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument("album1")
|
||||
|
||||
52
examples/concurrent_export.py
Normal file
52
examples/concurrent_export.py
Normal file
@@ -0,0 +1,52 @@
|
||||
"""Example for concurrent export of photos using osxphotos.PhotoExporter.export()
|
||||
|
||||
Note: concurrent export can only be used on Python 3.11 and later due to the way
|
||||
python's sqlite3 module is implemented. See https://docs.python.org/3/library/sqlite3.html#sqlite3.threadsafety
|
||||
for more information.
|
||||
"""
|
||||
|
||||
import concurrent.futures
|
||||
import os
|
||||
import time
|
||||
|
||||
import click
|
||||
|
||||
import osxphotos
|
||||
from osxphotos.cli import echo, query_command, verbose
|
||||
|
||||
|
||||
@query_command()
|
||||
@click.option(
|
||||
"--workers",
|
||||
metavar="WORKERS",
|
||||
help="Maximum number of worker threads to use for export. "
|
||||
"If not specified, it will default to the number of processors on the machine, multiplied by 5.",
|
||||
type=int,
|
||||
)
|
||||
@click.argument(
|
||||
"export_dir",
|
||||
type=click.Path(exists=True, file_okay=False, dir_okay=True, writable=True),
|
||||
)
|
||||
def export(workers, export_dir, photos: list[osxphotos.PhotoInfo], **kwargs):
|
||||
"""Export photos to EXPORT_DIR using concurrent export.
|
||||
Use --workers to specify the number of worker threads to use.
|
||||
|
||||
This simple example exports only the original photo and does not export
|
||||
edited versions, live photos, etc.
|
||||
"""
|
||||
workers = workers or os.cpu_count() * 5
|
||||
echo(f"Exporting {len(photos)} photos to {export_dir} using {workers} workers")
|
||||
start_t = time.perf_counter()
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=workers) as executor:
|
||||
futures = [executor.submit(p.export, export_dir) for p in photos]
|
||||
exported = []
|
||||
for future in concurrent.futures.as_completed(futures):
|
||||
exported.extend(future.result())
|
||||
end_t = time.perf_counter()
|
||||
echo(
|
||||
f"Exported {len(exported)} photos to {export_dir} in {end_t-start_t:.4f} seconds"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
export()
|
||||
22
examples/custom_sidecar.mako
Normal file
22
examples/custom_sidecar.mako
Normal file
@@ -0,0 +1,22 @@
|
||||
<%doc>
|
||||
This is an example Mako template for use with --sidecar-template
|
||||
For more information on Mako templates, see https://docs.makotemplates.org/en/latest/
|
||||
|
||||
The template will be passed three variables for rendering:
|
||||
photo: a PhotoInfo object for the photo being exported
|
||||
photo_path: a pathlib.Path object for the photo file being exported
|
||||
sidecar_path: a pathlib.Path object for the sidecar file being written
|
||||
</%doc>
|
||||
|
||||
<%def name="rating(photo)" filter="trim">\
|
||||
% if photo.favorite:
|
||||
★★★★★
|
||||
% else:
|
||||
★☆☆☆☆
|
||||
% endif
|
||||
</%def>\
|
||||
|
||||
Photo: ${photo_path.name}
|
||||
UUID: ${photo.uuid}
|
||||
Sidecar: ${sidecar_path.name}
|
||||
Rating: ${rating(photo)}
|
||||
11
examples/custom_sidecar_json.mako
Normal file
11
examples/custom_sidecar_json.mako
Normal file
@@ -0,0 +1,11 @@
|
||||
<%doc>
|
||||
Mako template to dump a full json representation of the photo object
|
||||
Can be run from the command line with:
|
||||
osxphotos export /path/to/export --sidecar-template custom_sidecar_json.mako "{filepath}.json" yes no yes
|
||||
|
||||
The template will be passed three variables for rendering:
|
||||
photo: a PhotoInfo object for the photo being exported
|
||||
photo_path: a pathlib.Path object for the photo file being exported
|
||||
sidecar_path: a pathlib.Path object for the sidecar file being written
|
||||
</%doc>
|
||||
${photo.json(shallow=False, indent=4)}
|
||||
223
examples/custom_sidecar_xmp.mako
Normal file
223
examples/custom_sidecar_xmp.mako
Normal file
@@ -0,0 +1,223 @@
|
||||
<%doc>
|
||||
This is an example Mako template for use with --sidecar-template which produces an XMP sidecar file
|
||||
For more information on Mako templates, see https://docs.makotemplates.org/en/latest/
|
||||
|
||||
The template will be passed three variables for rendering:
|
||||
photo: a PhotoInfo object for the photo being exported
|
||||
photo_path: a pathlib.Path object for the photo file being exported
|
||||
sidecar_path: a pathlib.Path object for the sidecar file being written
|
||||
</%doc>
|
||||
|
||||
<%def name="photoshop_sidecar_for_extension(extension)">
|
||||
% if extension is None:
|
||||
<photoshop:SidecarForExtension></photoshop:SidecarForExtension>
|
||||
% else:
|
||||
<photoshop:SidecarForExtension>${extension}</photoshop:SidecarForExtension>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="dc_description(desc)">
|
||||
% if desc is None:
|
||||
<dc:description>
|
||||
<rdf:Alt>
|
||||
<rdf:li xml:lang='x-default'/>
|
||||
</rdf:Alt>
|
||||
</dc:description>
|
||||
% else:
|
||||
<dc:description>
|
||||
<rdf:Alt>
|
||||
<rdf:li xml:lang='x-default'>${desc | x}</rdf:li>
|
||||
</rdf:Alt>
|
||||
</dc:description>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="dc_title(title)">
|
||||
% if title is None:
|
||||
<dc:title>
|
||||
<rdf:Alt>
|
||||
<rdf:li xml:lang='x-default'/>
|
||||
</rdf:Alt>
|
||||
</dc:title>
|
||||
% else:
|
||||
<dc:title>
|
||||
<rdf:Alt>
|
||||
<rdf:li xml:lang='x-default'>${title | x}</rdf:li>
|
||||
</rdf:Alt>
|
||||
</dc:title>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="dc_subject(subject)">
|
||||
% if subject:
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
% for subj in subject:
|
||||
<rdf:li>${subj | x}</rdf:li>
|
||||
% endfor
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="dc_datecreated(date)">
|
||||
% if date is not None:
|
||||
<photoshop:DateCreated>${date.isoformat()}</photoshop:DateCreated>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="iptc_personinimage(persons)">
|
||||
% if persons:
|
||||
<Iptc4xmpExt:PersonInImage>
|
||||
<rdf:Bag>
|
||||
% for person in persons:
|
||||
<rdf:li>${person | x}</rdf:li>
|
||||
% endfor
|
||||
</rdf:Bag>
|
||||
</Iptc4xmpExt:PersonInImage>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="dk_tagslist(keywords)">
|
||||
% if keywords:
|
||||
<digiKam:TagsList>
|
||||
<rdf:Seq>
|
||||
% for keyword in keywords:
|
||||
<rdf:li>${keyword | x}</rdf:li>
|
||||
% endfor
|
||||
</rdf:Seq>
|
||||
</digiKam:TagsList>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="adobe_createdate(date)">
|
||||
% if date is not None:
|
||||
<xmp:CreateDate>${date.strftime("%Y-%m-%dT%H:%M:%S")}</xmp:CreateDate>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="adobe_modifydate(date)">
|
||||
% if date is not None:
|
||||
<xmp:ModifyDate>${date.strftime("%Y-%m-%dT%H:%M:%S")}</xmp:ModifyDate>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="xmp_rating(rating)">
|
||||
% if rating is not None:
|
||||
<xmp:Rating>${rating}</xmp:Rating>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="gps_info(latitude, longitude)">
|
||||
% if latitude is not None and longitude is not None:
|
||||
<exif:GPSLongitude>${int(abs(longitude))},${(abs(longitude) % 1) * 60}${"E" if longitude >= 0 else "W"}</exif:GPSLongitude>
|
||||
<exif:GPSLatitude>${int(abs(latitude))},${(abs(latitude) % 1) * 60}${"N" if latitude >= 0 else "S"}</exif:GPSLatitude>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="mwg_face_regions(photo)">
|
||||
% if photo.face_info:
|
||||
<mwg-rs:Regions rdf:parseType="Resource">
|
||||
<mwg-rs:AppliedToDimensions rdf:parseType="Resource">
|
||||
<stDim:h>${photo.width if photo.orientation in [5, 6, 7, 8] else photo.height}</stDim:h>
|
||||
<stDim:w>${photo.height if photo.orientation in [5, 6, 7, 8] else photo.width}</stDim:w>
|
||||
<stDim:unit>pixel</stDim:unit>
|
||||
</mwg-rs:AppliedToDimensions>
|
||||
<mwg-rs:RegionList>
|
||||
<rdf:Bag>
|
||||
% for face in photo.face_info:
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<mwg-rs:Area rdf:parseType="Resource">
|
||||
<stArea:h>${'{0:.6f}'.format(face.mwg_rs_area.h)}</stArea:h>
|
||||
<stArea:w>${'{0:.6f}'.format(face.mwg_rs_area.w)}</stArea:w>
|
||||
<stArea:x>${'{0:.6f}'.format(face.mwg_rs_area.x)}</stArea:x>
|
||||
<stArea:y>${'{0:.6f}'.format(face.mwg_rs_area.y)}</stArea:y>
|
||||
<stArea:unit>normalized</stArea:unit>
|
||||
</mwg-rs:Area>
|
||||
<mwg-rs:Name>${face.name}</mwg-rs:Name>
|
||||
<mwg-rs:Rotation>${face.roll}</mwg-rs:Rotation>
|
||||
<mwg-rs:Type>Face</mwg-rs:Type>
|
||||
</rdf:li>
|
||||
% endfor
|
||||
</rdf:Bag>
|
||||
</mwg-rs:RegionList>
|
||||
</mwg-rs:Regions>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="mpri_face_regions(photo)">
|
||||
% if photo.face_info:
|
||||
<MP:RegionInfo rdf:parseType="Resource">
|
||||
<MPRI:Regions>
|
||||
<rdf:Bag>
|
||||
% for face in photo.face_info:
|
||||
<rdf:li rdf:parseType="Resource">
|
||||
<MPReg:PersonDisplayName>${face.name}</MPReg:PersonDisplayName>
|
||||
<MPReg:Rectangle>${'{0:.6f}'.format(face.mpri_reg_rect.x)}, ${'{0:.6f}'.format(face.mpri_reg_rect.y)}, ${'{0:.6f}'.format(face.mpri_reg_rect.h)}, ${'{0:.6f}'.format(face.mpri_reg_rect.w)}</MPReg:Rectangle>
|
||||
</rdf:li>
|
||||
% endfor
|
||||
</rdf:Bag>
|
||||
</MPRI:Regions>
|
||||
</MP:RegionInfo>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
|
||||
<?xpacket begin="${"\uFEFF"}" id="W5M0MpCehiHzreSzNTczkc9d"?>
|
||||
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="osxphotos">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
||||
<%
|
||||
extension = photo_path.suffix[1:].lower() if photo_path.suffix else ""
|
||||
%>
|
||||
${photoshop_sidecar_for_extension(extension)}
|
||||
${dc_description(photo.description)}
|
||||
${dc_title(photo.title)}
|
||||
<%
|
||||
subjects = photo.keywords + photo.persons
|
||||
%>
|
||||
${dc_subject(subjects)}
|
||||
${dc_datecreated(photo.date)}
|
||||
</rdf:Description>
|
||||
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
|
||||
${iptc_personinimage(photo.persons)}
|
||||
</rdf:Description>
|
||||
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
|
||||
${dk_tagslist(photo.keywords)}
|
||||
</rdf:Description>
|
||||
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
|
||||
${adobe_createdate(photo.date)}
|
||||
${adobe_modifydate(photo.date)}
|
||||
${xmp_rating("5" if photo.favorite else None)}
|
||||
</rdf:Description>
|
||||
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
|
||||
${gps_info(*photo.location)}
|
||||
</rdf:Description>
|
||||
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:mwg-rs="http://www.metadataworkinggroup.com/schemas/regions/"
|
||||
xmlns:stArea="http://ns.adobe.com/xmp/sType/Area#"
|
||||
xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#">
|
||||
${mwg_face_regions(photo)}
|
||||
</rdf:Description>
|
||||
|
||||
<rdf:Description rdf:about=""
|
||||
xmlns:MP="http://ns.microsoft.com/photo/1.2/"
|
||||
xmlns:MPRI="http://ns.microsoft.com/photo/1.2/t/RegionInfo#"
|
||||
xmlns:MPReg="http://ns.microsoft.com/photo/1.2/t/Region#">
|
||||
${mpri_face_regions(photo)}
|
||||
</rdf:Description>
|
||||
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
<?xpacket end="w"?>
|
||||
@@ -1,6 +1,7 @@
|
||||
import osxphotos
|
||||
import os.path
|
||||
|
||||
import osxphotos
|
||||
|
||||
|
||||
def main():
|
||||
db = osxphotos.utils.get_system_library_path()
|
||||
|
||||
@@ -32,7 +32,7 @@ import osxphotos
|
||||
default=False,
|
||||
)
|
||||
def export(export_path, default_album, library_path, edited):
|
||||
""" Export all photos, organized by album """
|
||||
"""Export all photos, organized by album"""
|
||||
export_path = os.path.expanduser(export_path)
|
||||
library_path = os.path.expanduser(library_path) if library_path else None
|
||||
|
||||
@@ -66,11 +66,11 @@ def export(export_path, default_album, library_path, edited):
|
||||
os.makedirs(dest_dir)
|
||||
|
||||
filename = p.original_filename
|
||||
# export the photo but only if --edited, photo has adjustments, and
|
||||
# export the photo but only if --edited, photo has adjustments, and
|
||||
# path_edited is not None (can be None if edited photo is missing)
|
||||
if edited and p.hasadjustments and p.path_edited:
|
||||
# export edited version
|
||||
# use original filename with _edited appended but make sure suffix is
|
||||
# use original filename with _edited appended but make sure suffix is
|
||||
# same as edited file
|
||||
edited_filename = f"{pathlib.Path(filename).stem}_edited{pathlib.Path(p.path_edited).suffix}"
|
||||
exported = p.export(dest_dir, edited_filename, edited=True)
|
||||
|
||||
@@ -32,7 +32,7 @@ import osxphotos
|
||||
default=None,
|
||||
)
|
||||
def export(export_path, library_path, uuid):
|
||||
""" export photos to export_path and draw faces """
|
||||
"""export photos to export_path and draw faces"""
|
||||
library_path = os.path.expanduser(library_path) if library_path else None
|
||||
if library_path is not None:
|
||||
photosdb = osxphotos.PhotosDB(library_path)
|
||||
@@ -61,7 +61,7 @@ def export(export_path, library_path, uuid):
|
||||
|
||||
|
||||
def get_circle_points(xy, radius):
|
||||
""" Returns tuples of (x0, y0), (x1, y1) for a circle centered at x, y with radius
|
||||
"""Returns tuples of (x0, y0), (x1, y1) for a circle centered at x, y with radius
|
||||
|
||||
Arguments:
|
||||
xy: tuple of x, y coordinates
|
||||
|
||||
126
examples/export_previews.py
Normal file
126
examples/export_previews.py
Normal file
@@ -0,0 +1,126 @@
|
||||
""" Export previews for photos in the Photos library
|
||||
|
||||
To run this with osxphotos on currently selected photos:
|
||||
|
||||
osxphotos run export_previews.py --selected export_path
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
import shutil
|
||||
|
||||
import click
|
||||
|
||||
import osxphotos
|
||||
from osxphotos.cli import echo, echo_error, query_command, verbose
|
||||
from osxphotos.cli.export import get_dirnames_from_template, get_filenames_from_template
|
||||
from osxphotos.cli.param_types import TemplateString
|
||||
from osxphotos.utils import pluralize
|
||||
|
||||
|
||||
@query_command
|
||||
@click.option("--dry-run", is_flag=True, help="Dry run, don't actually export")
|
||||
@click.option(
|
||||
"--directory",
|
||||
type=TemplateString(),
|
||||
help="Directory to export to under export_path. This is an osxphotos template string. "
|
||||
"For example, to export previews to directories based on creation date: "
|
||||
"--directory '{created.year}/{created.mm}/{created.dd}' ",
|
||||
)
|
||||
@click.option(
|
||||
"--filename",
|
||||
"filename_template",
|
||||
type=TemplateString(),
|
||||
help="Filename for exported preview. "
|
||||
"This is an osxphotos template string; "
|
||||
"for example, to export previews to filename based on creation date: "
|
||||
"--filename '{original_name}-{created.year}-{created.mm}-{created.dd}' ",
|
||||
)
|
||||
@click.argument(
|
||||
"export_dir", type=click.Path(exists=True, file_okay=False, dir_okay=True)
|
||||
)
|
||||
def export_previews(
|
||||
photos: list[osxphotos.PhotoInfo],
|
||||
dry_run: bool,
|
||||
directory: str,
|
||||
filename_template: str,
|
||||
export_dir: str,
|
||||
**kwargs,
|
||||
):
|
||||
"""Export previews for photos in the Photos library.
|
||||
|
||||
Pass one or more query options to select photos to export or use without query options
|
||||
to export all images.
|
||||
|
||||
If --directory is passed, the previews will be exported to subdirectories under export_path
|
||||
based on the template string passed to --directory. For example, to export previews to
|
||||
directories based on creation date: --directory '{created.year}/{created.mm}/{created.dd}'
|
||||
|
||||
If --filename is passed, the previews will be exported with the filename specified by the
|
||||
template string passed to --filename. For example, to export previews to filename based on
|
||||
creation date: --filename '{original_name}-{created.year}-{created.mm}-{created.dd}'
|
||||
|
||||
If --dry-run is passed, the previews will not actually be exported but the export will be
|
||||
simulated and the export paths printed to stdout.
|
||||
"""
|
||||
|
||||
verbose(f"Found {len(photos)} photo(s)")
|
||||
count = 0
|
||||
for photo in photos:
|
||||
try:
|
||||
# first derivative is the largest preview, so use that one
|
||||
preview = pathlib.Path(photo.path_derivatives[0])
|
||||
except IndexError:
|
||||
echo(f"No preview for {photo.original_filename} ({photo.uuid})")
|
||||
continue
|
||||
|
||||
verbose(f"Found preview for {photo.original_filename}: {preview}")
|
||||
count += export_preview_to_directory_with_filename(
|
||||
photo, preview, export_dir, directory, filename_template, dry_run
|
||||
)
|
||||
echo(f"Exported {count} preview {pluralize(count, 'image', 'images')}")
|
||||
|
||||
|
||||
def export_preview_to_directory_with_filename(
|
||||
photo: osxphotos.PhotoInfo,
|
||||
preview_path: pathlib.Path,
|
||||
export_dir: str,
|
||||
directory: str,
|
||||
filename_template: str,
|
||||
dry_run: bool,
|
||||
) -> int:
|
||||
"""Export preview for photo to directory with filename; returns count of images exported"""
|
||||
count = 0
|
||||
for dirname in get_dirnames_from_template(
|
||||
photo=photo,
|
||||
directory=directory,
|
||||
export_by_date=False,
|
||||
dest=export_dir,
|
||||
dry_run=dry_run,
|
||||
):
|
||||
for filename in get_filenames_from_template(
|
||||
photo=photo,
|
||||
filename_template=filename_template,
|
||||
export_dir=export_dir,
|
||||
dest_path=dirname,
|
||||
original_name=True,
|
||||
):
|
||||
# need to change filename extension to match preview
|
||||
filename = pathlib.Path(filename).with_suffix(preview_path.suffix)
|
||||
dest_path = pathlib.Path(dirname) / filename
|
||||
echo(
|
||||
f"Exporting preview for {photo.original_filename} ({photo.uuid}) to {dest_path}"
|
||||
)
|
||||
if not dry_run:
|
||||
try:
|
||||
shutil.copy(preview_path, dest_path)
|
||||
except Exception as e:
|
||||
echo_error(f"Error exporting preview: {e}")
|
||||
continue
|
||||
count += 1
|
||||
return count
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
export_previews()
|
||||
@@ -77,7 +77,9 @@ def place_folder(photo: osxphotos.PhotoInfo) -> str:
|
||||
return ""
|
||||
|
||||
|
||||
def photos_folders(photo: osxphotos.PhotoInfo, options: osxphotos.phototemplate.RenderOptions, **kwargs) -> Union[List, str]:
|
||||
def photos_folders(
|
||||
photo: osxphotos.PhotoInfo, options: osxphotos.phototemplate.RenderOptions, **kwargs
|
||||
) -> Union[List, str]:
|
||||
"""template function for use with --directory to export photos in a folder structure similar to Photos
|
||||
|
||||
Args:
|
||||
|
||||
@@ -29,7 +29,9 @@ def main():
|
||||
exported = photo.export(tempdir.name, use_photos_export=True, timeout=300)
|
||||
if photo.hasadjustments:
|
||||
exported.extend(
|
||||
photo.export(tempdir.name, use_photos_export=True, edited=True, timeout=300)
|
||||
photo.export(
|
||||
tempdir.name, use_photos_export=True, edited=True, timeout=300
|
||||
)
|
||||
)
|
||||
for filename in exported:
|
||||
print(f"Removing temporary file {filename}")
|
||||
|
||||
@@ -10,7 +10,7 @@ from osxphotos._constants import TIME_DELTA
|
||||
|
||||
@dataclass
|
||||
class Comment:
|
||||
""" Class for shared photo comments """
|
||||
"""Class for shared photo comments"""
|
||||
|
||||
uuid: str
|
||||
sort_fok: int
|
||||
@@ -22,7 +22,7 @@ class Comment:
|
||||
|
||||
@dataclass
|
||||
class Like:
|
||||
""" Class for shared photo likes """
|
||||
"""Class for shared photo likes"""
|
||||
|
||||
uuid: str
|
||||
sort_fok: int
|
||||
@@ -32,10 +32,10 @@ class Like:
|
||||
|
||||
|
||||
def get_shared_person_info(photosdb, hashed_person_id):
|
||||
""" returns tuple of (first name, last name, full name)
|
||||
for person invited to shared album with
|
||||
"""returns tuple of (first name, last name, full name)
|
||||
for person invited to shared album with
|
||||
ZINVITEEHASHEDPERSONID = hashed_person_id
|
||||
|
||||
|
||||
Args:
|
||||
photosdb: a osxphotos.PhotosDB object
|
||||
hashed_person_id: str, value of ZINVITEEHASHEDPERSONID to lookup
|
||||
@@ -66,12 +66,12 @@ def get_shared_person_info(photosdb, hashed_person_id):
|
||||
|
||||
|
||||
def get_comments(photosdb, uuid):
|
||||
""" return comments and likes, if any, for photo with uuid
|
||||
"""return comments and likes, if any, for photo with uuid
|
||||
|
||||
Args:
|
||||
photosdb: a osxphotos.PhotosDB object
|
||||
uuid: uuid of the photo
|
||||
|
||||
|
||||
Returns:
|
||||
tuple of (list of comments as Comment objects or [] if no comments, list of likes as Like objects or [] if no likes)
|
||||
"""
|
||||
|
||||
@@ -15,14 +15,14 @@ import time
|
||||
import click
|
||||
|
||||
import osxphotos
|
||||
from osxphotos.cli import get_photos_db, _list_libraries
|
||||
from osxphotos.cli import _list_libraries, get_photos_db
|
||||
|
||||
|
||||
def show(photo):
|
||||
""" open image with default image viewer
|
||||
|
||||
Note: This is for debugging only -- it will actually open any filetype which could
|
||||
be very, very bad.
|
||||
"""open image with default image viewer
|
||||
|
||||
Note: This is for debugging only -- it will actually open any filetype which could
|
||||
be very, very bad.
|
||||
|
||||
Args:
|
||||
photo: PhotoInfo object or a path to a photo on disk
|
||||
|
||||
@@ -1,57 +1,88 @@
|
||||
""" Example function for use with osxphotos export --post-function option """
|
||||
|
||||
from typing import Callable
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
from typing import Any, Callable
|
||||
|
||||
from osxphotos import ExportResults, PhotoInfo
|
||||
from osxphotos.cli import echo_error
|
||||
|
||||
|
||||
def post_function(
|
||||
photo: PhotoInfo, results: ExportResults, verbose: Callable, **kwargs
|
||||
):
|
||||
photo: PhotoInfo, results: ExportResults, verbose: Callable[[Any], None], **kwargs
|
||||
) -> ExportResults | None:
|
||||
"""Call this with osxphotos export /path/to/export --post-function post_function.py::post_function
|
||||
This will get called immediately after the photo has been exported
|
||||
|
||||
Args:
|
||||
photo: PhotoInfo instance for the photo that's just been exported
|
||||
see https://rhettbull.github.io/osxphotos/reference.html#osxphotos.PhotoInfo for details
|
||||
results: ExportResults instance with information about the files associated with the exported photo
|
||||
see https://rhettbull.github.io/osxphotos/reference.html#osxphotos.ExportResults for details
|
||||
verbose: A function to print verbose output if --verbose is set; if --verbose is not set, acts as a no-op (nothing gets printed)
|
||||
**kwargs: reserved for future use; recommend you include **kwargs so your function still works if additional arguments are added in future versions
|
||||
|
||||
Returns:
|
||||
ExportResults instance or None
|
||||
If returning an ExportResults instance, it must be a new instance; do not modify the instance passed in as an argument.
|
||||
You should set only the following values in ExportResults:
|
||||
user_written: list[str], list of files written by your function
|
||||
user_skipped: list[str], list of files skipped by your function
|
||||
user_error: list[tuple[str, str]], list of tuples of (filename, error) for any errors generated by your function
|
||||
For full description of ExportResults see: https://rhettbull.github.io/osxphotos/reference.html#osxphotos.ExportResults
|
||||
|
||||
Notes:
|
||||
Use verbose(str) instead of print if you want your function to conditionally output text depending on --verbose flag
|
||||
Any string printed with verbose that contains "warning" or "error" (case-insensitive) will be printed with the appropriate warning or error color
|
||||
Will not be called if --dry-run flag is enabled
|
||||
Will be called immediately after export and before any --post-command commands are executed
|
||||
The function will not be called if --dry-run flag is enabled
|
||||
The function be called immediately after export and before any --post-command commands are executed
|
||||
If your function does not write any files, you can optionally return None instead of an ExportResults instance
|
||||
If you return ExportResults, any files in user_written or user_skipped will be included when
|
||||
writing reports and will be preserved when using --cleanup
|
||||
If you want files previously written by the post_function, but not written this time,
|
||||
to be preserved when using --cleanup, you should include them in user_skipped
|
||||
|
||||
If the function raises an exception, osxphotos will abort the export and exit with an error.
|
||||
If you want the export to continue, you should catch any exceptions and return an ExportResults instance
|
||||
with the error(s) in specified in ExportResults.user_error which is a list of tuples of (filename, error)
|
||||
|
||||
The verbose function can be used to print text to stdout if --verbose is set
|
||||
If --verbose is not set, verbose acts as a no-op (nothing gets printed)
|
||||
Verbose output may be stylized with tags as follows; tags must be enclosed in square brackets
|
||||
and closed with [/] to end the style:
|
||||
[change]: something change
|
||||
[no_change]: indicate no change
|
||||
[count]: a count
|
||||
[error]: an error
|
||||
[filename]: a filename
|
||||
[filepath]: a filepath
|
||||
[num]: a number
|
||||
[time]: a time or date
|
||||
[tz]: a timezone
|
||||
[warning]: a warning
|
||||
[uuid]: a uuid
|
||||
"""
|
||||
|
||||
# ExportResults has the following properties
|
||||
# fields with filenames contain the full path to the file
|
||||
# exported: list of all files exported
|
||||
# new: list of all new files exported (--update)
|
||||
# updated: list of all files updated (--update)
|
||||
# skipped: list of all files skipped (--update)
|
||||
# exif_updated: list of all files that were updated with --exiftool
|
||||
# touched: list of all files that had date updated with --touch-file
|
||||
# converted_to_jpeg: list of files converted to jpeg with --convert-to-jpeg
|
||||
# sidecar_json_written: list of all JSON sidecar files written
|
||||
# sidecar_json_skipped: list of all JSON sidecar files skipped (--update)
|
||||
# sidecar_exiftool_written: list of all exiftool sidecar files written
|
||||
# sidecar_exiftool_skipped: list of all exiftool sidecar files skipped (--update)
|
||||
# sidecar_xmp_written: list of all XMP sidecar files written
|
||||
# sidecar_xmp_skipped: list of all XMP sidecar files skipped (--update)
|
||||
# missing: list of all missing files
|
||||
# error: list tuples of (filename, error) for any errors generated during export
|
||||
# exiftool_warning: list of tuples of (filename, warning) for any warnings generated by exiftool with --exiftool
|
||||
# exiftool_error: list of tuples of (filename, error) for any errors generated by exiftool with --exiftool
|
||||
# xattr_written: list of files that had extended attributes written
|
||||
# xattr_skipped: list of files that where extended attributes were skipped (--update)
|
||||
# deleted_files: list of deleted files
|
||||
# deleted_directories: list of deleted directories
|
||||
# exported_album: list of tuples of (filename, album_name) for exported files added to album with --add-exported-to-album
|
||||
# skipped_album: list of tuples of (filename, album_name) for skipped files added to album with --add-skipped-to-album
|
||||
# missing_album: list of tuples of (filename, album_name) for missing files added to album with --add-missing-to-album
|
||||
# metadata_changed: list of filenames that had metadata changes since last export
|
||||
|
||||
for filename in results.exported:
|
||||
post_results = ExportResults()
|
||||
for filename in results.exported + results.skipped:
|
||||
# do your processing here
|
||||
verbose(f"post_function: {photo.original_filename} exported as {filename}")
|
||||
|
||||
# simulate doing some processing
|
||||
new_filename = pathlib.Path(f"{filename}.new")
|
||||
if new_filename.exists():
|
||||
verbose(f"Skipping file [filepath]{new_filename}[/] as it already exists")
|
||||
post_results.user_skipped.append(new_filename)
|
||||
else:
|
||||
verbose(f"Writing new file [filepath]{new_filename}[/]")
|
||||
new_filename.touch()
|
||||
post_results.user_written.append(new_filename)
|
||||
|
||||
# if you encounter an error, add it to user_error
|
||||
# echo_error will print the error to stderr with the appropriate formatting
|
||||
|
||||
# echo_error(f"Encountered an error processing [filepath]{filename}[/]: [error]some error[/]")
|
||||
# post_results.user_error.append((filename, "some error"))
|
||||
|
||||
# if your function does not write any files, you can return None
|
||||
return post_results
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
""" Example function for use with osxphotos import --post-function option """
|
||||
|
||||
import typing as t
|
||||
import photoscript
|
||||
import pathlib
|
||||
import typing as t
|
||||
|
||||
import photoscript
|
||||
|
||||
from osxphotos.cli.import_cli import ReportRecord
|
||||
|
||||
|
||||
def post_function(
|
||||
photo: photoscript.Photo, filepath: pathlib.Path, verbose: t.Callable, **kwargs
|
||||
photo: photoscript.Photo,
|
||||
filepath: pathlib.Path,
|
||||
verbose: t.Callable,
|
||||
report_record: ReportRecord,
|
||||
**kwargs,
|
||||
):
|
||||
"""Call this with osxphotos import /file/to/import --post-function post_function.py::post_function
|
||||
This will get called immediately after the photo has been imported into Photos
|
||||
@@ -15,6 +23,7 @@ def post_function(
|
||||
photo: photoscript.Photo instance for the photo that's just been imported
|
||||
filepath: pathlib.Path to the file that was imported (this is the path to the source file, not the path inside the Photos library)
|
||||
verbose: A function to print verbose output if --verbose is set; if --verbose is not set, acts as a no-op (nothing gets printed)
|
||||
report_record: ReportRecord instance for the photo that's just been imported; update this if you want to change the report output
|
||||
**kwargs: reserved for future use; recommend you include **kwargs so your function still works if additional arguments are added in future versions
|
||||
|
||||
Notes:
|
||||
@@ -25,4 +34,16 @@ def post_function(
|
||||
|
||||
# add a note to the photo's description
|
||||
verbose("Adding note to description")
|
||||
photo.description = f"{photo.description} (imported with osxphotos)"
|
||||
description = photo.description
|
||||
description = (
|
||||
f"{description} (imported with osxphotos)"
|
||||
if description
|
||||
else "(imported with osxphotos)"
|
||||
)
|
||||
|
||||
# update report_record if you modify the photo and want the report to reflect the change
|
||||
# the report_record object passed to the function is mutable so you can update it directly
|
||||
report_record.description = description
|
||||
|
||||
# update the photo's description via the Photo object
|
||||
photo.description = description
|
||||
|
||||
@@ -3,6 +3,7 @@ import os.path
|
||||
|
||||
import osxphotos
|
||||
|
||||
|
||||
def main():
|
||||
db = os.path.expanduser("~/Pictures/Photos Library.photoslibrary")
|
||||
photosdb = osxphotos.PhotosDB(db)
|
||||
@@ -15,11 +16,14 @@ def main():
|
||||
print(photosdb.albums_as_dict)
|
||||
|
||||
# find all photos with Keyword = Foo and containing John Smith
|
||||
photos = photosdb.photos(keywords=["Foo"],persons=["John Smith"])
|
||||
photos = photosdb.photos(keywords=["Foo"], persons=["John Smith"])
|
||||
|
||||
# find all photos that include Alice Smith but do not contain the keyword Bar
|
||||
photos = [p for p in photosdb.photos(persons=["Alice Smith"])
|
||||
if p not in photosdb.photos(keywords=["Bar"]) ]
|
||||
photos = [
|
||||
p
|
||||
for p in photosdb.photos(persons=["Alice Smith"])
|
||||
if p not in photosdb.photos(keywords=["Bar"])
|
||||
]
|
||||
for p in photos:
|
||||
print(
|
||||
p.uuid,
|
||||
@@ -34,5 +38,6 @@ def main():
|
||||
p.path,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
from typing import List
|
||||
|
||||
|
||||
def myfilter(values: List[str]) -> List[str]:
|
||||
""" Custom filter to append "foo-" to template value """
|
||||
"""Custom filter to append "foo-" to template value"""
|
||||
values = ["foo-" + val for val in values]
|
||||
return values
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ from typing import Callable
|
||||
|
||||
from osxphotos import ExportResults, PhotoInfo
|
||||
from osxphotos.exiftool import ExifTool
|
||||
from osxphotos.utils import normalize_unicode
|
||||
from osxphotos.unicode import normalize_unicode
|
||||
|
||||
# Update this for your custom keyword to rating mapping
|
||||
RATINGS = {
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""__init__.py for osxphotos"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from ._constants import AlbumSortOrder
|
||||
@@ -9,19 +13,28 @@ from .exiftool import ExifTool
|
||||
from .export_db import ExportDB, ExportDBTemp
|
||||
from .fileutil import FileUtil, FileUtilNoOp
|
||||
from .momentinfo import MomentInfo
|
||||
from .personinfo import PersonInfo
|
||||
from .personinfo import FaceInfo, PersonInfo
|
||||
from .photoexporter import ExportOptions, ExportResults, PhotoExporter
|
||||
from .photoinfo import PhotoInfo
|
||||
from .photosalbum import PhotosAlbum, PhotosAlbumPhotoScript
|
||||
from .photosdb import PhotosDB
|
||||
from .photosdb._photosdb_process_comments import CommentInfo, LikeInfo
|
||||
from .phototables import PhotoTables
|
||||
from .phototemplate import PhotoTemplate
|
||||
from .placeinfo import PlaceInfo
|
||||
from .platform import is_macos
|
||||
from .queryoptions import QueryOptions
|
||||
from .scoreinfo import ScoreInfo
|
||||
from .searchinfo import SearchInfo
|
||||
from .utils import _get_logger
|
||||
|
||||
if is_macos:
|
||||
from .photosalbum import PhotosAlbum, PhotosAlbumPhotoScript
|
||||
|
||||
# configure logging; every module in osxphotos should use this logger
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG,
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(filename)s - %(lineno)d - %(message)s",
|
||||
)
|
||||
logger: logging.Logger = logging.getLogger("osxphotos")
|
||||
if not is_debug():
|
||||
logging.disable(logging.DEBUG)
|
||||
|
||||
@@ -35,14 +48,17 @@ __all__ = [
|
||||
"ExportDBTemp",
|
||||
"ExportOptions",
|
||||
"ExportResults",
|
||||
"FaceInfo",
|
||||
"FileUtil",
|
||||
"FileUtilNoOp",
|
||||
"FolderInfo",
|
||||
"ImportInfo",
|
||||
"LikeInfo",
|
||||
"MomentInfo",
|
||||
"PersonInfo",
|
||||
"PhotoExporter",
|
||||
"PhotoInfo",
|
||||
"PhotoTables",
|
||||
"PhotoTemplate",
|
||||
"PhotosAlbum",
|
||||
"PhotosAlbumPhotoScript",
|
||||
@@ -53,8 +69,7 @@ __all__ = [
|
||||
"ScoreInfo",
|
||||
"SearchInfo",
|
||||
"__version__",
|
||||
"_get_logger",
|
||||
"is_debug",
|
||||
"logger",
|
||||
"set_debug",
|
||||
"FolderInfo",
|
||||
]
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
"""
|
||||
Constants used by osxphotos
|
||||
"""
|
||||
""" Constants used by osxphotos """
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os.path
|
||||
import sqlite3
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
logger: logging.Logger = logging.getLogger("osxphotos")
|
||||
|
||||
APP_NAME = "osxphotos"
|
||||
|
||||
OSXPHOTOS_URL = "https://github.com/RhetTbull/osxphotos"
|
||||
@@ -14,23 +18,23 @@ OSXPHOTOS_URL = "https://github.com/RhetTbull/osxphotos"
|
||||
# Apple Epoch is Jan 1, 2001
|
||||
TIME_DELTA = (datetime(2001, 1, 1, 0, 0) - datetime(1970, 1, 1, 0, 0)).total_seconds()
|
||||
|
||||
# Unicode format to use for comparing strings
|
||||
UNICODE_FORMAT = "NFC"
|
||||
|
||||
# which Photos library database versions have been tested
|
||||
# Photos 2.0 (10.12.6) == 2622
|
||||
# Photos 3.0 (10.13.6) == 3301
|
||||
# Photos 4.0 (10.14.5) == 4016
|
||||
# Photos 4.0 (10.14.6) == 4025
|
||||
# Photos 5.0 (10.15.0) == 6000 or 5001
|
||||
# Photos 5.0+ (10.15.0) == 6000 or 5001
|
||||
_TESTED_DB_VERSIONS = ["6000", "5001", "4025", "4016", "3301", "2622"]
|
||||
|
||||
# database model versions (applies to Photos 5, Photos 6)
|
||||
# database model versions (applies to Photos 5+)
|
||||
# these come from PLModelVersion key in binary plist in Z_METADATA.Z_PLIST
|
||||
# Photos 5 (10.15.1) == 13537
|
||||
# Photos 5 (10.15.4, 10.15.5, 10.15.6) == 13703
|
||||
# Photos 6 (10.16.0 Beta) == 14104
|
||||
_TEST_MODEL_VERSIONS = ["13537", "13703", "14104"]
|
||||
# Photos 7 (12.0.1) == 15323
|
||||
# Photos 8 (13.0.0) == 16320
|
||||
# Photos 9 (14.0.0 dev preview) = 17120
|
||||
_TEST_MODEL_VERSIONS = ["13537", "13703", "14104", "15323", "16320", "17120"]
|
||||
|
||||
_PHOTOS_2_VERSION = "2622"
|
||||
|
||||
@@ -38,7 +42,7 @@ _PHOTOS_2_VERSION = "2622"
|
||||
_PHOTOS_3_VERSION = "3301"
|
||||
|
||||
# versions 5.0 and later have a different database structure
|
||||
_PHOTOS_4_VERSION = "4025" # latest Mojove version on 10.14.6
|
||||
_PHOTOS_4_VERSION = "4025" # latest Mojave version on 10.14.6
|
||||
_PHOTOS_5_VERSION = "5000" # I've seen both 5001 and 6000. 6000 is most common on Catalina and up but there are some version 5001 database in the wild
|
||||
|
||||
# Ranges for model version by Photos version
|
||||
@@ -46,8 +50,15 @@ _PHOTOS_5_MODEL_VERSION = [13000, 13999]
|
||||
_PHOTOS_6_MODEL_VERSION = [14000, 14999]
|
||||
_PHOTOS_7_MODEL_VERSION = [15000, 15999] # Dev preview: 15134, 12.1: 15331
|
||||
_PHOTOS_8_MODEL_VERSION = [16000, 16999] # Ventura dev preview: 16119
|
||||
_PHOTOS_9_MODEL_VERSION = [17000, 17999] # Sonoma dev preview: 17120
|
||||
|
||||
# some table names differ between Photos 5 and Photos 6
|
||||
# the preview versions of 12.0.0 had a difference schema for syndication info so need to check model version before processing
|
||||
_PHOTOS_SYNDICATION_MODEL_VERSION = 15323 # 12.0.1
|
||||
|
||||
# shared iCloud library versions; dev preview doesn't contain same columns as release version
|
||||
_PHOTOS_SHARED_LIBRARY_VERSION = 16320 # 13.0
|
||||
|
||||
# some table names differ between Photos 5 and later versions
|
||||
_DB_TABLE_NAMES = {
|
||||
5: {
|
||||
"ASSET": "ZGENERICASSET",
|
||||
@@ -60,6 +71,8 @@ _DB_TABLE_NAMES = {
|
||||
"ASSET_ALBUM_JOIN": "Z_26ASSETS.Z_26ALBUMS",
|
||||
"ASSET_ALBUM_TABLE": "Z_26ASSETS",
|
||||
"HDR_TYPE": "ZCUSTOMRENDEREDVALUE",
|
||||
"DETECTED_FACE_PERSON_FK": "ZDETECTEDFACE.ZPERSON",
|
||||
"DETECTED_FACE_ASSET_FK": "ZDETECTEDFACE.ZASSET",
|
||||
},
|
||||
6: {
|
||||
"ASSET": "ZASSET",
|
||||
@@ -72,6 +85,8 @@ _DB_TABLE_NAMES = {
|
||||
"ASSET_ALBUM_JOIN": "Z_26ASSETS.Z_26ALBUMS",
|
||||
"ASSET_ALBUM_TABLE": "Z_26ASSETS",
|
||||
"HDR_TYPE": "ZCUSTOMRENDEREDVALUE",
|
||||
"DETECTED_FACE_PERSON_FK": "ZDETECTEDFACE.ZPERSON",
|
||||
"DETECTED_FACE_ASSET_FK": "ZDETECTEDFACE.ZASSET",
|
||||
},
|
||||
7: {
|
||||
"ASSET": "ZASSET",
|
||||
@@ -84,6 +99,8 @@ _DB_TABLE_NAMES = {
|
||||
"ASSET_ALBUM_JOIN": "Z_27ASSETS.Z_27ALBUMS",
|
||||
"ASSET_ALBUM_TABLE": "Z_27ASSETS",
|
||||
"HDR_TYPE": "ZHDRTYPE",
|
||||
"DETECTED_FACE_PERSON_FK": "ZDETECTEDFACE.ZPERSON",
|
||||
"DETECTED_FACE_ASSET_FK": "ZDETECTEDFACE.ZASSET",
|
||||
},
|
||||
8: {
|
||||
"ASSET": "ZASSET",
|
||||
@@ -96,6 +113,22 @@ _DB_TABLE_NAMES = {
|
||||
"ASSET_ALBUM_JOIN": "Z_28ASSETS.Z_28ALBUMS",
|
||||
"ASSET_ALBUM_TABLE": "Z_28ASSETS",
|
||||
"HDR_TYPE": "ZHDRTYPE",
|
||||
"DETECTED_FACE_PERSON_FK": "ZDETECTEDFACE.ZPERSON",
|
||||
"DETECTED_FACE_ASSET_FK": "ZDETECTEDFACE.ZASSET",
|
||||
},
|
||||
9: {
|
||||
"ASSET": "ZASSET",
|
||||
"KEYWORD_JOIN": "Z_1KEYWORDS.Z_40KEYWORDS",
|
||||
"ALBUM_JOIN": "Z_28ASSETS.Z_3ASSETS",
|
||||
"ALBUM_SORT_ORDER": "Z_28ASSETS.Z_FOK_3ASSETS",
|
||||
"IMPORT_FOK": "null",
|
||||
"DEPTH_STATE": "ZASSET.ZDEPTHTYPE",
|
||||
"UTI_ORIGINAL": "ZINTERNALRESOURCE.ZCOMPACTUTI",
|
||||
"ASSET_ALBUM_JOIN": "Z_28ASSETS.Z_28ALBUMS",
|
||||
"ASSET_ALBUM_TABLE": "Z_28ASSETS",
|
||||
"HDR_TYPE": "ZHDRTYPE",
|
||||
"DETECTED_FACE_PERSON_FK": "ZDETECTEDFACE.ZPERSONFORFACE",
|
||||
"DETECTED_FACE_ASSET_FK": "ZDETECTEDFACE.ZASSETFORFACE",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -123,6 +156,10 @@ _TESTED_OS_VERSIONS = [
|
||||
("12", "6"),
|
||||
("13", "0"),
|
||||
("13", "1"),
|
||||
("13", "2"),
|
||||
("13", "3"),
|
||||
("13", "4"),
|
||||
("14", "0"),
|
||||
]
|
||||
|
||||
# Photos 5 has persons who are empty string if unidentified face
|
||||
@@ -138,7 +175,9 @@ _PHOTOS_5_SHARED_PHOTO_PATH = "resources/cloudsharing/data"
|
||||
_PHOTOS_8_SHARED_PHOTO_PATH = "scopes/cloudsharing/data"
|
||||
|
||||
# Where are shared iCloud derivatives located?
|
||||
_PHOTOS_5_SHARED_DERIVATIVE_PATH = "resources/cloudsharing/resources/derivatives/masters"
|
||||
_PHOTOS_5_SHARED_DERIVATIVE_PATH = (
|
||||
"resources/cloudsharing/resources/derivatives/masters"
|
||||
)
|
||||
_PHOTOS_8_SHARED_DERIVATIVE_PATH = "scopes/cloudsharing/resources/derivatives/masters"
|
||||
|
||||
# What type of file? Based on ZGENERICASSET.ZKIND in Photos 5 database
|
||||
@@ -178,6 +217,9 @@ _MAX_IPTC_KEYWORD_LEN = 64
|
||||
# If anyone has a keyword matching this, then too bad...
|
||||
_OSXPHOTOS_NONE_SENTINEL = "OSXPhotosXYZZY42_Sentinel$"
|
||||
|
||||
# Lock file extension for reserving filenames when exporting
|
||||
_OSXPHOTOS_LOCK_EXTENSION = ".osxphotos.lock"
|
||||
|
||||
|
||||
class SearchCategory:
|
||||
"""SearchInfo categories for Photos 5+; corresponds to categories in database/search/psi.sqlite:groups.category
|
||||
@@ -213,11 +255,11 @@ class SearchCategory:
|
||||
TITLE = 2017
|
||||
DESCRIPTION = 2018
|
||||
HOME = 2020
|
||||
WORK = 2036
|
||||
PERSON = 2021
|
||||
ACTIVITY = 2027
|
||||
HOLIDAY = 2029
|
||||
SEASON = 2030
|
||||
WORK = 2036
|
||||
VENUE = 2038
|
||||
VENUE_TYPE = 2039
|
||||
PHOTO_TYPE_VIDEO = 2044
|
||||
@@ -230,6 +272,7 @@ class SearchCategory:
|
||||
PHOTO_TYPE_PORTRAIT = 2053
|
||||
PHOTO_TYPE_SELFIES = 2054
|
||||
PHOTO_TYPE_FAVORITES = 2055
|
||||
PHOTO_TYPE_ANIMATED = None # Photos 8+ only
|
||||
MEDIA_TYPES = [
|
||||
PHOTO_TYPE_VIDEO,
|
||||
PHOTO_TYPE_SLOMO,
|
||||
@@ -244,7 +287,23 @@ class SearchCategory:
|
||||
]
|
||||
PHOTO_NAME = 2056
|
||||
CAMERA = None # Photos 8+ only
|
||||
TEXT_FOUND = None # Photos 8+ only
|
||||
DETECTED_TEXT = None # Photos 8+ only
|
||||
SOURCE = None # Photos 8+ only
|
||||
|
||||
@classmethod
|
||||
def categories(cls) -> dict[int, str]:
|
||||
"""Return categories as dict of value: name"""
|
||||
# a bit of a hack to basically reverse the enum
|
||||
return {
|
||||
value: name
|
||||
for name, value in cls.__dict__.items()
|
||||
if name is not None
|
||||
and not name.startswith("__")
|
||||
and not callable(name)
|
||||
and name.isupper()
|
||||
and not isinstance(value, (list, dict, tuple))
|
||||
}
|
||||
|
||||
|
||||
class SearchCategory_Photos8(SearchCategory):
|
||||
@@ -252,6 +311,20 @@ class SearchCategory_Photos8(SearchCategory):
|
||||
|
||||
# Many of the category values changed in Ventura / Photos 8
|
||||
# and some new categories were added
|
||||
CITY = 5
|
||||
LOCALITY_4 = 4
|
||||
SUB_LOCALITY_5 = None
|
||||
SUB_LOCALITY_6 = 6
|
||||
LOCALITY_8 = 8
|
||||
NAMED_AREA = 7
|
||||
ALL_LOCALITY = [
|
||||
LOCALITY_4,
|
||||
SUB_LOCALITY_6,
|
||||
LOCALITY_8,
|
||||
NAMED_AREA,
|
||||
]
|
||||
HOME = 1000
|
||||
WORK = 1001
|
||||
LABEL = 1500
|
||||
MONTH = 1100
|
||||
YEAR = 1101
|
||||
@@ -261,11 +334,55 @@ class SearchCategory_Photos8(SearchCategory):
|
||||
TITLE = 1201
|
||||
DESCRIPTION = 1202
|
||||
DETECTED_TEXT = 1203 # new in Photos 8
|
||||
TEXT_FOUND = 1205 # new in Photos 8
|
||||
PERSON = 1300
|
||||
ACTIVITY = 1600
|
||||
VENUE = 1700
|
||||
VENUE_TYPE = 1701
|
||||
PHOTO_TYPE_VIDEO = 1901
|
||||
PHOTO_TYPE_SELFIES = 1915
|
||||
PHOTO_TYPE_LIVE = 1906
|
||||
PHOTO_TYPE_PORTRAIT = 1914
|
||||
PHOTO_TYPE_FAVORITES = 2000
|
||||
PHOTO_TYPE_PANORAMA = 1908
|
||||
PHOTO_TYPE_TIMELAPSE = 1909
|
||||
PHOTO_TYPE_SLOMO = 1905
|
||||
PHOTO_TYPE_BURSTS = 1913
|
||||
PHOTO_TYPE_SCREENSHOT = 1907
|
||||
PHOTO_TYPE_ANIMATED = 1912
|
||||
PHOTO_TYPE_RAW = 1902
|
||||
MEDIA_TYPES = [
|
||||
PHOTO_TYPE_VIDEO,
|
||||
PHOTO_TYPE_SLOMO,
|
||||
PHOTO_TYPE_LIVE,
|
||||
PHOTO_TYPE_SCREENSHOT,
|
||||
PHOTO_TYPE_PANORAMA,
|
||||
PHOTO_TYPE_TIMELAPSE,
|
||||
PHOTO_TYPE_BURSTS,
|
||||
PHOTO_TYPE_PORTRAIT,
|
||||
PHOTO_TYPE_SELFIES,
|
||||
PHOTO_TYPE_FAVORITES,
|
||||
PHOTO_TYPE_ANIMATED,
|
||||
]
|
||||
PHOTO_NAME = 2100
|
||||
CAMERA = 2300 # new in Photos 8
|
||||
SOURCE = 2200 # new in Photos 8, shows the app/software source for the photo, e.g. Messages, Safari, etc.
|
||||
|
||||
@classmethod
|
||||
def categories(cls) -> dict[int, str]:
|
||||
"""Return categories as dict of value: name"""
|
||||
# need to get the categories from the base class and update with the new values
|
||||
classdict = SearchCategory.__dict__.copy()
|
||||
classdict |= cls.__dict__.copy()
|
||||
return {
|
||||
value: name
|
||||
for name, value in classdict.items()
|
||||
if name is not None
|
||||
and not name.startswith("__")
|
||||
and not callable(name)
|
||||
and name.isupper()
|
||||
and not isinstance(value, (list, dict, tuple))
|
||||
}
|
||||
|
||||
|
||||
def search_category_factory(version: int) -> SearchCategory:
|
||||
@@ -274,7 +391,7 @@ def search_category_factory(version: int) -> SearchCategory:
|
||||
|
||||
|
||||
# Max filename length on MacOS
|
||||
MAX_FILENAME_LEN = 255
|
||||
MAX_FILENAME_LEN = 255 - len(_OSXPHOTOS_LOCK_EXTENSION)
|
||||
|
||||
# Max directory name length on MacOS
|
||||
MAX_DIRNAME_LEN = 255
|
||||
@@ -379,3 +496,16 @@ PROFILE_SORT_KEYS = [
|
||||
"time",
|
||||
"tottime",
|
||||
]
|
||||
|
||||
UUID_PATTERN = (
|
||||
r"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"
|
||||
)
|
||||
# Reference: https://docs.python.org/3/library/sqlite3.html?highlight=sqlite3%20threadsafety#sqlite3.threadsafety
|
||||
# and https://docs.python.org/3/library/sqlite3.html?highlight=sqlite3%20threadsafety#sqlite3.connect
|
||||
# 3: serialized mode; Threads may share the module, connections and cursors
|
||||
# 3 is the default in the python.org python 3.11 distribution
|
||||
# earlier versions of python.org python 3.x default to 1 which means threads may not share
|
||||
# sqlite3 connections and thus PhotoInfo.export() cannot be used in a multithreaded environment
|
||||
# pass SQLITE_CHECK_SAME_THREAD to sqlite3.connect() to enable multithreaded access on systems that support it
|
||||
SQLITE_CHECK_SAME_THREAD = not sqlite3.threadsafety == 3
|
||||
logger.debug(f"{SQLITE_CHECK_SAME_THREAD=}, {sqlite3.threadsafety=}")
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.56.2"
|
||||
__version__ = "0.61.0"
|
||||
|
||||
@@ -18,6 +18,7 @@ from ._constants import (
|
||||
_PHOTOS_4_VERSION,
|
||||
_PHOTOS_5_ALBUM_KIND,
|
||||
_PHOTOS_5_FOLDER_KIND,
|
||||
_PHOTOS_5_VERSION,
|
||||
TIME_DELTA,
|
||||
AlbumSortOrder,
|
||||
)
|
||||
@@ -49,9 +50,8 @@ def sort_list_by_keys(values, sort_keys):
|
||||
ValueError: raised if len(values) != len(sort_keys)
|
||||
"""
|
||||
if len(values) != len(sort_keys):
|
||||
return ValueError("values and sort_keys must have same length")
|
||||
|
||||
return list(zip(*sorted(zip(sort_keys, values))))[1]
|
||||
raise ValueError("values and sort_keys must be same length")
|
||||
return [x for _, x in sorted(zip(sort_keys, values))]
|
||||
|
||||
|
||||
class AlbumInfoBaseClass:
|
||||
@@ -61,7 +61,7 @@ class AlbumInfoBaseClass:
|
||||
including folders, photos, etc.
|
||||
"""
|
||||
|
||||
def __init__(self, db=None, uuid=None):
|
||||
def __init__(self, db, uuid):
|
||||
self._uuid = uuid
|
||||
self._db = db
|
||||
self._title = self._db._dbalbum_details[uuid]["title"]
|
||||
@@ -121,7 +121,8 @@ class AlbumInfoBaseClass:
|
||||
@property
|
||||
def end_date(self):
|
||||
"""For Albums, return end date (most recent image) of album or None for albums with no images
|
||||
For Import Sessions, return end date of import sessions (when import was completed)"""
|
||||
For Import Sessions, return end date of import sessions (when import was completed)
|
||||
"""
|
||||
try:
|
||||
return self._end_date
|
||||
except AttributeError:
|
||||
@@ -163,6 +164,16 @@ class AlbumInfoBaseClass:
|
||||
self._owner = None
|
||||
return self._owner
|
||||
|
||||
def asdict(self):
|
||||
"""Return album info as a dict; does not include photos"""
|
||||
return {
|
||||
"uuid": self.uuid,
|
||||
"creation_date": self.creation_date,
|
||||
"start_date": self.start_date,
|
||||
"end_date": self.end_date,
|
||||
"owner": self.owner,
|
||||
}
|
||||
|
||||
def __len__(self):
|
||||
"""return number of photos contained in album"""
|
||||
return len(self.photos)
|
||||
@@ -174,6 +185,10 @@ class AlbumInfo(AlbumInfoBaseClass):
|
||||
including folders, photos, etc.
|
||||
"""
|
||||
|
||||
def __init__(self, db, uuid):
|
||||
super().__init__(db=db, uuid=uuid)
|
||||
self._title = self._db._dbalbum_details[uuid]["title"]
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
"""return title / name of album"""
|
||||
@@ -205,10 +220,11 @@ class AlbumInfo(AlbumInfoBaseClass):
|
||||
|
||||
@property
|
||||
def folder_names(self):
|
||||
"""return hierarchical list of folders the album is contained in
|
||||
"""Return hierarchical list of folders the album is contained in
|
||||
the folder list is in form:
|
||||
["Top level folder", "sub folder 1", "sub folder 2", ...]
|
||||
returns empty list if album is not in any folders"""
|
||||
or empty list if album is not in any folders
|
||||
"""
|
||||
|
||||
try:
|
||||
return self._folder_names
|
||||
@@ -218,10 +234,9 @@ class AlbumInfo(AlbumInfoBaseClass):
|
||||
|
||||
@property
|
||||
def folder_list(self):
|
||||
"""return hierarchical list of folders the album is contained in
|
||||
as list of FolderInfo objects in form
|
||||
["Top level folder", "sub folder 1", "sub folder 2", ...]
|
||||
returns empty list if album is not in any folders"""
|
||||
"""Returns list of FolderInfo objects for each folder the album is contained in
|
||||
or empty list if album is not in any folders
|
||||
"""
|
||||
|
||||
try:
|
||||
return self._folders
|
||||
@@ -246,7 +261,7 @@ class AlbumInfo(AlbumInfoBaseClass):
|
||||
parent_pk = self._db._dbalbum_details[self._uuid]["parentfolder"]
|
||||
self._parent = (
|
||||
FolderInfo(db=self._db, uuid=self._db._dbalbums_pk[parent_pk])
|
||||
if parent_pk != self._db._folder_root_pk
|
||||
if parent_pk is not None and parent_pk != self._db._folder_root_pk
|
||||
else None
|
||||
)
|
||||
return self._parent
|
||||
@@ -281,27 +296,79 @@ class AlbumInfo(AlbumInfoBaseClass):
|
||||
f"Photo with uuid {photo.uuid} does not appear to be in this album"
|
||||
)
|
||||
|
||||
def asdict(self):
|
||||
"""Return album info as a dict; does not include photos"""
|
||||
dict_data = super().asdict()
|
||||
dict_data["title"] = self.title
|
||||
dict_data["folder_names"] = self.folder_names
|
||||
dict_data["folder_list"] = [f.uuid for f in self.folder_list]
|
||||
dict_data["sort_order"] = self.sort_order
|
||||
dict_data["parent"] = self.parent.uuid if self.parent else None
|
||||
return dict_data
|
||||
|
||||
|
||||
class ImportInfo(AlbumInfoBaseClass):
|
||||
"""Information about import sessions"""
|
||||
|
||||
def __init__(self, db, uuid):
|
||||
self._uuid = uuid
|
||||
self._db = db
|
||||
|
||||
if self._db._db_version >= _PHOTOS_5_VERSION:
|
||||
return super().__init__(db=db, uuid=uuid)
|
||||
|
||||
import_session = self._db._db_import_group[self._uuid]
|
||||
try:
|
||||
self._creation_date_timestamp = import_session[3]
|
||||
except (ValueError, TypeError, KeyError):
|
||||
self._creation_date_timestamp = datetime(1970, 1, 1)
|
||||
self._start_date_timestamp = self._creation_date_timestamp
|
||||
self._end_date_timestamp = self._creation_date_timestamp
|
||||
self._title = import_session[2]
|
||||
self._local_tz = get_local_tz(
|
||||
datetime.fromtimestamp(self._creation_date_timestamp + TIME_DELTA)
|
||||
)
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
"""return title / name of import session"""
|
||||
return self._title
|
||||
|
||||
@property
|
||||
def photos(self):
|
||||
"""return list of photos contained in import session"""
|
||||
try:
|
||||
return self._photos
|
||||
except AttributeError:
|
||||
uuid_list, sort_order = zip(
|
||||
*[
|
||||
(uuid, self._db._dbphotos[uuid]["fok_import_session"])
|
||||
for uuid in self._db._dbphotos
|
||||
if self._db._dbphotos[uuid]["import_uuid"] == self.uuid
|
||||
if self._db._db_version >= _PHOTOS_5_VERSION:
|
||||
uuid_list, sort_order = zip(
|
||||
*[
|
||||
(uuid, self._db._dbphotos[uuid]["fok_import_session"])
|
||||
for uuid in self._db._dbphotos
|
||||
if self._db._dbphotos[uuid]["import_uuid"] == self.uuid
|
||||
]
|
||||
)
|
||||
sorted_uuid = sort_list_by_keys(uuid_list, sort_order)
|
||||
self._photos = self._db.photos_by_uuid(sorted_uuid)
|
||||
else:
|
||||
import_photo_uuids = [
|
||||
u
|
||||
for u in self._db._dbphotos
|
||||
if self._db._dbphotos[u]["import_uuid"] == self.uuid
|
||||
]
|
||||
)
|
||||
sorted_uuid = sort_list_by_keys(uuid_list, sort_order)
|
||||
self._photos = self._db.photos_by_uuid(sorted_uuid)
|
||||
self._photos = self._db.photos_by_uuid(import_photo_uuids)
|
||||
return self._photos
|
||||
|
||||
def asdict(self):
|
||||
"""Return import info as a dict; does not include photos"""
|
||||
return {
|
||||
"uuid": self.uuid,
|
||||
"creation_date": self.creation_date,
|
||||
"start_date": self.start_date,
|
||||
"end_date": self.end_date,
|
||||
"title": self.title,
|
||||
}
|
||||
|
||||
def __bool__(self):
|
||||
"""Always returns True
|
||||
A photo without an import session will return None for import_info,
|
||||
@@ -309,13 +376,32 @@ class ImportInfo(AlbumInfoBaseClass):
|
||||
"""
|
||||
return True
|
||||
|
||||
|
||||
class ProjectInfo(AlbumInfo):
|
||||
"""
|
||||
ProjectInfo with info about projects
|
||||
Projects are cards, calendars, slideshows, etc.
|
||||
"""
|
||||
|
||||
...
|
||||
@property
|
||||
def folder_names(self):
|
||||
"""Return hierarchical list of folders the album is contained in
|
||||
the folder list is in form:
|
||||
["Top level folder", "sub folder 1", "sub folder 2", ...]
|
||||
or empty list if album is not in any folders
|
||||
"""
|
||||
|
||||
# projects are not in folders
|
||||
return []
|
||||
|
||||
@property
|
||||
def folder_list(self):
|
||||
"""Returns list of FolderInfo objects for each folder the album is contained in
|
||||
or empty list if album is not in any folders
|
||||
"""
|
||||
|
||||
# projects are not in folders
|
||||
return []
|
||||
|
||||
|
||||
class FolderInfo:
|
||||
@@ -386,7 +472,7 @@ class FolderInfo:
|
||||
parent_pk = self._db._dbalbum_details[self._uuid]["parentfolder"]
|
||||
self._parent = (
|
||||
FolderInfo(db=self._db, uuid=self._db._dbalbums_pk[parent_pk])
|
||||
if parent_pk != self._db._folder_root_pk
|
||||
if parent_pk is not None and parent_pk != self._db._folder_root_pk
|
||||
else None
|
||||
)
|
||||
return self._parent
|
||||
@@ -416,6 +502,16 @@ class FolderInfo:
|
||||
self._folders = folders
|
||||
return self._folders
|
||||
|
||||
def asdict(self):
|
||||
"""Return folder info as a dict"""
|
||||
return {
|
||||
"title": self.title,
|
||||
"uuid": self.uuid,
|
||||
"parent": self.parent.uuid if self.parent is not None else None,
|
||||
"subfolders": [f.uuid for f in self.subfolders],
|
||||
"albums": [a.uuid for a in self.album_info],
|
||||
}
|
||||
|
||||
def __len__(self):
|
||||
"""returns count of folders + albums contained in the folder"""
|
||||
return len(self.subfolders) + len(self.album_info)
|
||||
|
||||
@@ -13,6 +13,7 @@ from osxphotos.debug import (
|
||||
set_debug,
|
||||
wrap_function,
|
||||
)
|
||||
from osxphotos.platform import is_macos
|
||||
|
||||
# apply any debug functions
|
||||
# need to do this before importing anything else so that the debug functions
|
||||
@@ -46,8 +47,19 @@ if args.get("--debug", False):
|
||||
from .about import about
|
||||
from .albums import albums
|
||||
from .cli import cli_main
|
||||
from .common import get_photos_db, load_uuid_from_file
|
||||
from .cli_commands import (
|
||||
abort,
|
||||
echo,
|
||||
echo_error,
|
||||
logger,
|
||||
query_command,
|
||||
selection_command,
|
||||
verbose,
|
||||
)
|
||||
from .cli_params import DB_OPTION, DEBUG_OPTIONS, JSON_OPTION
|
||||
from .common import OSXPHOTOS_HIDDEN, get_photos_db
|
||||
from .debug_dump import debug_dump
|
||||
from .docs import docs_command
|
||||
from .dump import dump
|
||||
from .exiftool_cli import exiftool
|
||||
from .export import export
|
||||
@@ -57,48 +69,71 @@ from .help import help
|
||||
from .info import info
|
||||
from .install_uninstall_run import install, run, uninstall
|
||||
from .keywords import keywords
|
||||
from .kvstore import kvstore
|
||||
from .labels import labels
|
||||
from .list import _list_libraries, list_libraries
|
||||
from .orphans import orphans
|
||||
from .persons import persons
|
||||
from .photo_inspect import photo_inspect
|
||||
from .places import places
|
||||
from .query import query
|
||||
from .repl import repl
|
||||
from .snap_diff import diff, snap
|
||||
from .theme import theme
|
||||
from .tutorial import tutorial
|
||||
from .uuid import uuid
|
||||
from .version import version
|
||||
|
||||
if is_macos:
|
||||
from .add_locations import add_locations
|
||||
from .batch_edit import batch_edit
|
||||
from .import_cli import import_cli
|
||||
from .photo_inspect import photo_inspect
|
||||
from .show_command import show
|
||||
from .sync import sync
|
||||
from .timewarp import timewarp
|
||||
from .uuid import uuid
|
||||
|
||||
install_traceback()
|
||||
|
||||
__all__ = [
|
||||
"abort",
|
||||
"about",
|
||||
"add_locations",
|
||||
"albums",
|
||||
"batch_edit",
|
||||
"cli_main",
|
||||
"debug_dump",
|
||||
"diff",
|
||||
"docs_command",
|
||||
"dump",
|
||||
"echo",
|
||||
"echo_error",
|
||||
"exiftool_cli",
|
||||
"export",
|
||||
"exportdb",
|
||||
"grep",
|
||||
"help",
|
||||
"import_cli",
|
||||
"info",
|
||||
"install",
|
||||
"keywords",
|
||||
"kvstore",
|
||||
"labels",
|
||||
"list_libraries",
|
||||
"list_libraries",
|
||||
"load_uuid_from_file",
|
||||
"logger",
|
||||
"orphans",
|
||||
"persons",
|
||||
"photo_inspect",
|
||||
"places",
|
||||
"query",
|
||||
"query_command",
|
||||
"repl",
|
||||
"run",
|
||||
"selection_command",
|
||||
"set_debug",
|
||||
"show",
|
||||
"snap",
|
||||
"tutorial",
|
||||
"uuid",
|
||||
"verbose",
|
||||
]
|
||||
|
||||
187
osxphotos/cli/add_locations.py
Normal file
187
osxphotos/cli/add_locations.py
Normal file
@@ -0,0 +1,187 @@
|
||||
"""Add missing location data to photos in Photos.app using nearest neighbor."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
|
||||
import click
|
||||
|
||||
import osxphotos
|
||||
from osxphotos.platform import assert_macos
|
||||
from osxphotos.queryoptions import IncompatibleQueryOptions, query_options_from_kwargs
|
||||
from osxphotos.utils import pluralize
|
||||
|
||||
from .cli_params import QUERY_OPTIONS, THEME_OPTION, TIMESTAMP_OPTION, VERBOSE_OPTION
|
||||
from .click_rich_echo import rich_click_echo as echo
|
||||
from .click_rich_echo import rich_echo_error as echo_error
|
||||
from .param_types import TimeOffset
|
||||
from .rich_progress import rich_progress
|
||||
from .verbose import get_verbose_console, verbose_print
|
||||
|
||||
assert_macos()
|
||||
|
||||
import photoscript
|
||||
|
||||
|
||||
def get_location(
|
||||
photos: list[osxphotos.PhotoInfo], idx: int, window: datetime.timedelta
|
||||
) -> osxphotos.PhotoInfo | None:
|
||||
"""Find nearest neighbor with location data within window of time.
|
||||
|
||||
Args:
|
||||
photo: PhotoInfo object
|
||||
idx: index of photo in list of photos
|
||||
window: window of time to search for nearest neighbor
|
||||
|
||||
Returns:
|
||||
nearest neighbor PhotoInfo object or None if no neighbor found
|
||||
"""
|
||||
idx_back = None
|
||||
idx_forward = None
|
||||
if idx > 0:
|
||||
# search backwards in time
|
||||
for i in range(idx - 1, -1, -1):
|
||||
if (
|
||||
photos[idx].date - photos[i].date <= window
|
||||
and None not in photos[i].location
|
||||
):
|
||||
idx_back = i
|
||||
break
|
||||
|
||||
if idx < len(photos) - 1:
|
||||
# search forwards in time
|
||||
for i in range(idx + 1, len(photos)):
|
||||
if (
|
||||
photos[i].date - photos[idx].date <= window
|
||||
and None not in photos[i].location
|
||||
):
|
||||
idx_forward = i
|
||||
break
|
||||
|
||||
if idx_back is not None and idx_forward is not None:
|
||||
# found location in both directions
|
||||
# use location closest in time
|
||||
if (
|
||||
photos[idx].date - photos[idx_back].date
|
||||
< photos[idx_forward].date - photos[idx].date
|
||||
):
|
||||
return photos[idx_back]
|
||||
else:
|
||||
return photos[idx_forward]
|
||||
elif idx_back is not None:
|
||||
return photos[idx_back]
|
||||
elif idx_forward is not None:
|
||||
return photos[idx_forward]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
@click.command(name="add-locations")
|
||||
@click.option(
|
||||
"--window",
|
||||
"-w",
|
||||
type=TimeOffset(),
|
||||
default="1 hr",
|
||||
help="Window of time to search for nearest neighbor; "
|
||||
"searches +/- window of time. Default is 1 hour. "
|
||||
"Format is one of 'HH:MM:SS', 'D days', 'H hours' (or hr), 'M minutes' (or min), "
|
||||
"'S seconds' (or sec), 'S' (where S is seconds).",
|
||||
)
|
||||
@click.option(
|
||||
"--dry-run",
|
||||
is_flag=True,
|
||||
help="Don't actually add location, just print what would be done. "
|
||||
"Most useful with --verbose.",
|
||||
)
|
||||
@VERBOSE_OPTION
|
||||
@TIMESTAMP_OPTION
|
||||
@QUERY_OPTIONS
|
||||
@THEME_OPTION
|
||||
@click.pass_obj
|
||||
@click.pass_context
|
||||
def add_locations(
|
||||
ctx, cli_ob, window, dry_run, verbose_flag, timestamp, theme, **kwargs
|
||||
):
|
||||
"""Add missing location data to photos in Photos.app using nearest neighbor.
|
||||
|
||||
This command will search for photos that are missing location data and look
|
||||
for the nearest neighbor photo within a given window of time that contains
|
||||
location information. If a photo is found within the window of time, the
|
||||
location of the nearest neighbor will be used to update the location of the
|
||||
photo.
|
||||
|
||||
For example, if you took pictures with your iPhone and also with a camera that
|
||||
doesn't have location information, you can use this command to add location
|
||||
information to the photos taken with the camera from those taken with the
|
||||
iPhone.
|
||||
|
||||
If you have many photos with missing location information but no nearest neighbor
|
||||
within the window of time, you could add location information to some photos manually
|
||||
then run this command again to add location information to the remaining photos.
|
||||
|
||||
You can specify a subset of photos to update using the query options. For example,
|
||||
`--selected` to update only the selected photos, `--added-after 2020-01-01` to update
|
||||
only photos added after Jan 1, 2020, etc.
|
||||
|
||||
Example:
|
||||
|
||||
Add location data to all photos with missing location data within a ±2 hour window:
|
||||
|
||||
`osxphotos add-locations --window "2 hr" --verbose`
|
||||
|
||||
The add-locations command assumes that photos already have the correct date and time.
|
||||
If you have photos that are missing both location data and date/time information,
|
||||
you can use `osxphotos timewarp` to add date/time information to the photos and then
|
||||
use `osxphotos add-locations` to add location information.
|
||||
See `osxphotos help timewarp` for more information.
|
||||
"""
|
||||
verbose = verbose_print(verbose_flag, timestamp, theme=theme)
|
||||
|
||||
verbose("Searching for photos with missing location data...")
|
||||
|
||||
try:
|
||||
query_options = query_options_from_kwargs(**kwargs)
|
||||
except IncompatibleQueryOptions as e:
|
||||
echo_error("Incompatible query options")
|
||||
echo_error(ctx.obj.group.commands["repl"].get_help(ctx))
|
||||
ctx.exit(1)
|
||||
|
||||
photosdb = osxphotos.PhotosDB(verbose=verbose)
|
||||
photos = photosdb.query(query_options)
|
||||
|
||||
# sort photos by date
|
||||
photos = sorted(photos, key=lambda p: p.date)
|
||||
|
||||
num_photos = len(photos)
|
||||
missing_location = 0
|
||||
found_location = 0
|
||||
verbose(f"Processing {len(photos)} photos, window = ±{window}...")
|
||||
with rich_progress(console=get_verbose_console(), mock=verbose_flag) as progress:
|
||||
task = progress.add_task(
|
||||
f"Processing [num]{num_photos}[/] {pluralize(len(photos), 'photo', 'photos')}, window = ±{window}",
|
||||
total=num_photos,
|
||||
)
|
||||
for idx, photo in enumerate(photos):
|
||||
if None in photo.location:
|
||||
missing_location += 1
|
||||
verbose(
|
||||
f"Processing [filename]{photo.original_filename}[/] ([uuid]{photo.uuid}[/])"
|
||||
)
|
||||
if neighbor := get_location(photos, idx, window):
|
||||
verbose(
|
||||
f"Adding location {neighbor.location} to [filename]{photo.original_filename}[/] ([uuid]{photo.uuid}[/])"
|
||||
f" from [filename]{neighbor.original_filename}[/] ([uuid]{neighbor.uuid}[/])"
|
||||
)
|
||||
found_location += 1
|
||||
if not dry_run:
|
||||
photoscript.Photo(photo.uuid).location = neighbor.location
|
||||
else:
|
||||
verbose(
|
||||
f"No location found for [filename]{photo.original_filename}[/] ([uuid]{photo.uuid}[/])"
|
||||
)
|
||||
progress.advance(task)
|
||||
echo(
|
||||
f"Done. Processed: [num]{num_photos}[/] photos, "
|
||||
f"missing location: [num]{missing_location}[/], "
|
||||
f"found location: [num]{found_location}[/] "
|
||||
)
|
||||
@@ -6,12 +6,12 @@ import click
|
||||
import yaml
|
||||
|
||||
import osxphotos
|
||||
|
||||
from .common import DB_ARGUMENT, DB_OPTION, JSON_OPTION, get_photos_db
|
||||
from .list import _list_libraries
|
||||
|
||||
from osxphotos._constants import _PHOTOS_4_VERSION
|
||||
|
||||
from .cli_params import DB_ARGUMENT, DB_OPTION, JSON_OPTION
|
||||
from .common import get_photos_db
|
||||
from .list import _list_libraries
|
||||
|
||||
|
||||
@click.command()
|
||||
@DB_OPTION
|
||||
@@ -36,7 +36,8 @@ def albums(ctx, cli_obj, db, json_, photos_library):
|
||||
if photosdb.db_version > _PHOTOS_4_VERSION:
|
||||
albums["shared albums"] = photosdb.albums_shared_as_dict
|
||||
|
||||
if json_ or cli_obj.json:
|
||||
# cli_obj will be None if called from pytest
|
||||
if json_ or (cli_obj and cli_obj.json):
|
||||
click.echo(json.dumps(albums, ensure_ascii=False))
|
||||
else:
|
||||
click.echo(yaml.dump(albums, sort_keys=False, allow_unicode=True))
|
||||
|
||||
315
osxphotos/cli/batch_edit.py
Normal file
315
osxphotos/cli/batch_edit.py
Normal file
@@ -0,0 +1,315 @@
|
||||
"""
|
||||
batch-edit command for osxphotos CLI
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import functools
|
||||
import json
|
||||
import sys
|
||||
|
||||
import click
|
||||
|
||||
import osxphotos
|
||||
from osxphotos.phototemplate import RenderOptions
|
||||
from osxphotos.platform import assert_macos
|
||||
from osxphotos.sqlitekvstore import SQLiteKVStore
|
||||
|
||||
assert_macos()
|
||||
|
||||
import photoscript
|
||||
|
||||
from .cli_commands import echo, echo_error, selection_command, verbose
|
||||
from .kvstore import kvstore
|
||||
from .param_types import Latitude, Longitude, TemplateString
|
||||
|
||||
|
||||
@selection_command(name="batch-edit")
|
||||
@click.option(
|
||||
"--title",
|
||||
metavar="TITLE_TEMPLATE",
|
||||
type=TemplateString(),
|
||||
help="Set title of photo.",
|
||||
)
|
||||
@click.option(
|
||||
"--description",
|
||||
metavar="DESCRIPTION_TEMPLATE",
|
||||
type=TemplateString(),
|
||||
help="Set description of photo.",
|
||||
)
|
||||
@click.option(
|
||||
"--keyword",
|
||||
metavar="KEYWORD_TEMPLATE",
|
||||
type=TemplateString(),
|
||||
multiple=True,
|
||||
help="Add keywords to photo. May be specified multiple times.",
|
||||
)
|
||||
@click.option(
|
||||
"--replace-keywords",
|
||||
is_flag=True,
|
||||
help="When specified with --keyword, replace existing keywords. "
|
||||
"Default is to add to existing keywords.",
|
||||
)
|
||||
@click.option(
|
||||
"--location",
|
||||
metavar="LATITUDE LONGITUDE",
|
||||
type=click.Tuple([Latitude(), Longitude()]),
|
||||
help="Set location of photo. "
|
||||
"Must be specified as a pair of numbers with latitude in the range -90 to 90 and longitude in the range -180 to 180.",
|
||||
)
|
||||
@click.option("--dry-run", is_flag=True, help="Don't actually change anything.")
|
||||
@click.option(
|
||||
"--undo",
|
||||
is_flag=True,
|
||||
help="Restores photo metadata to what it was prior to the last batch edit. "
|
||||
"May be combined with --dry-run.",
|
||||
)
|
||||
def batch_edit(
|
||||
photos: list[osxphotos.PhotoInfo],
|
||||
title,
|
||||
description,
|
||||
keyword,
|
||||
replace_keywords,
|
||||
location,
|
||||
dry_run,
|
||||
undo,
|
||||
**kwargs,
|
||||
):
|
||||
"""
|
||||
Batch edit photo metadata such as title, description, keywords, etc.
|
||||
Operates on currently selected photos.
|
||||
|
||||
Select one or more photos in Photos then run this command to edit the metadata.
|
||||
|
||||
For example:
|
||||
|
||||
\b
|
||||
osxphotos batch-edit \\
|
||||
--verbose \\
|
||||
--title "California vacation 2023 {created.year}-{created.dd}-{created.mm} {counter:03d}" \\
|
||||
--description "{place.name}" \\
|
||||
--keyword "Family" --keyword "Travel"
|
||||
|
||||
This will set the title to "California vacation 2023 2023-02-20 001", and so on,
|
||||
the description to the reverse geolocation place name,
|
||||
and add the keywords "Family" and "Travel".
|
||||
|
||||
--title, --description, and --keyword may be any valid template string.
|
||||
See https://rhettbull.github.io/osxphotos/template_help.html
|
||||
or `osxphotos docs` for more information on the osxphotos template system.
|
||||
"""
|
||||
|
||||
if not title and not description and not keyword and not location and not undo:
|
||||
echo_error(
|
||||
"[error] Must specify at least one of: "
|
||||
" --title, --description, --keyword, --location, --undo. "
|
||||
"Use --help for more information."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
if undo and (title or description or keyword or location):
|
||||
echo_error(
|
||||
"[error] Cannot specify --undo and any options other than --dry-run. "
|
||||
"Use --help for more information."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
if replace_keywords and not keyword:
|
||||
echo_error(
|
||||
"[error] Cannot specify --replace-keywords without --keyword. "
|
||||
"Use --help for more information."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
if not photos:
|
||||
echo_error("[error] No photos selected")
|
||||
sys.exit(1)
|
||||
|
||||
# sort photos by date so that {counter} order is correct
|
||||
photos.sort(key=lambda p: p.date)
|
||||
|
||||
undo_store = kvstore("batch_edit")
|
||||
verbose(f"Undo database stored in [filepath]{undo_store.path}", level=2)
|
||||
|
||||
echo(f"Processing [num]{len(photos)}[/] photos...")
|
||||
for photo in photos:
|
||||
verbose(
|
||||
f"Processing [filename]{photo.original_filename}[/] ([uuid]{photo.uuid}[/])"
|
||||
)
|
||||
if undo:
|
||||
undo_photo_edits(photo, undo_store, dry_run)
|
||||
continue
|
||||
save_photo_undo_info(undo_store, photo)
|
||||
set_photo_title_from_template(photo, title, dry_run)
|
||||
set_photo_description_from_template(photo, description, dry_run)
|
||||
set_photo_keywords_from_template(photo, keyword, replace_keywords, dry_run)
|
||||
set_photo_location(photo, location, dry_run)
|
||||
|
||||
|
||||
# cache photoscript Photo object to avoid re-creating it for each photo
|
||||
# maxsize=1 as this function is called repeatedly for each photo then
|
||||
# the next photo is processed
|
||||
@functools.lru_cache(maxsize=1)
|
||||
def photoscript_photo(photo: osxphotos.PhotoInfo) -> photoscript.Photo:
|
||||
"""Return photoscript Photo object for photo"""
|
||||
return photoscript.Photo(photo.uuid)
|
||||
|
||||
|
||||
def save_photo_undo_info(undo_store: SQLiteKVStore, photo: osxphotos.PhotoInfo):
|
||||
"""Save undo information to undo store"""
|
||||
undo_store[photo.uuid] = photo.json()
|
||||
|
||||
|
||||
def undo_photo_edits(
|
||||
photo: osxphotos.PhotoInfo, undo_store: SQLiteKVStore, dry_run: bool
|
||||
):
|
||||
"""Undo edits for photo"""
|
||||
if not (undo_info := undo_store.get(photo.uuid)):
|
||||
verbose(
|
||||
f"[warning] No undo information for photo [filename]{photo.original_filename}[/] ([uuid]{photo.uuid}[/])"
|
||||
)
|
||||
return
|
||||
undo_info = json.loads(undo_info)
|
||||
ps_photo = photoscript_photo(photo)
|
||||
exiting_title, exiting_description, exiting_keywords, exiting_location = (
|
||||
photo.title,
|
||||
photo.description,
|
||||
sorted(photo.keywords),
|
||||
photo.location,
|
||||
)
|
||||
previous_title, previous_description, previous_keywords, previous_location = (
|
||||
undo_info.get("title"),
|
||||
undo_info.get("description"),
|
||||
sorted(undo_info.get("keywords")),
|
||||
(undo_info.get("latitude"), undo_info.get("longitude")),
|
||||
)
|
||||
verbose(
|
||||
f"Undoing edits for [filename]{photo.original_filename}[/] ([uuid]{photo.uuid}[/])"
|
||||
)
|
||||
for name, existing, previous in (
|
||||
("title", exiting_title, previous_title),
|
||||
("description", exiting_description, previous_description),
|
||||
("keywords", exiting_keywords, previous_keywords),
|
||||
("location", exiting_location, previous_location),
|
||||
):
|
||||
if existing != previous:
|
||||
verbose(
|
||||
f" [i]{name}[/]: [change]{existing}[/] -> [no_change]{previous}[/]"
|
||||
)
|
||||
if not dry_run:
|
||||
setattr(ps_photo, name, previous)
|
||||
else:
|
||||
verbose(f" [i]{name} (no change)[/]: [no_change]{existing}[/]", level=2)
|
||||
|
||||
|
||||
def set_photo_title_from_template(
|
||||
photo: osxphotos.PhotoInfo, title_template: str, dry_run: bool
|
||||
):
|
||||
"""Set photo title from template"""
|
||||
if not title_template:
|
||||
return
|
||||
|
||||
# don't render None values
|
||||
render_options = RenderOptions(none_str="")
|
||||
|
||||
title_string, _ = photo.render_template(title_template, render_options)
|
||||
title_string = [ts for ts in title_string if ts]
|
||||
if not title_string:
|
||||
verbose(
|
||||
f"No title returned from template, nothing to do: [bold]{title_template}"
|
||||
)
|
||||
return
|
||||
|
||||
if len(title_string) > 1:
|
||||
echo_error(
|
||||
f"[error] Title template must return a single string: [bold]{title_string}"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
verbose(f"Setting [i]title[/i] to [bold]{title_string[0]}")
|
||||
if not dry_run:
|
||||
ps_photo = photoscript_photo(photo)
|
||||
ps_photo.title = title_string[0]
|
||||
|
||||
|
||||
def set_photo_description_from_template(
|
||||
photo: osxphotos.PhotoInfo, description_template: str, dry_run: bool
|
||||
):
|
||||
"""Set photo description from template"""
|
||||
if not description_template:
|
||||
return
|
||||
|
||||
# don't render None values
|
||||
render_options = RenderOptions(none_str="")
|
||||
|
||||
description_string, _ = photo.render_template(description_template, render_options)
|
||||
description_string = [ds for ds in description_string if ds]
|
||||
if not description_string:
|
||||
verbose(
|
||||
f"No description returned from template, nothing to do: [bold]{description_template}"
|
||||
)
|
||||
return
|
||||
|
||||
if len(description_string) > 1:
|
||||
echo_error(
|
||||
f"[error] Description template must return a single string: [bold]{description_string}"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
verbose(f"Setting [i]description[/] to [bold]{description_string[0]}")
|
||||
if not dry_run:
|
||||
ps_photo = photoscript_photo(photo)
|
||||
ps_photo.description = description_string[0]
|
||||
|
||||
|
||||
def set_photo_keywords_from_template(
|
||||
photo: osxphotos.PhotoInfo,
|
||||
keyword_template: list[str],
|
||||
replace_keywords: bool,
|
||||
dry_run: bool,
|
||||
):
|
||||
"""Set photo keywords from template"""
|
||||
if not keyword_template:
|
||||
return
|
||||
|
||||
# don't render None values
|
||||
render_options = RenderOptions(none_str="")
|
||||
|
||||
keywords = set()
|
||||
for kw in keyword_template:
|
||||
kw_string, _ = photo.render_template(kw, render_options)
|
||||
if kw_string:
|
||||
# filter out empty strings
|
||||
keywords.update([k for k in kw_string if k])
|
||||
|
||||
if not keywords:
|
||||
verbose(
|
||||
f"No keywords returned from template, nothing to do: [bold]{keyword_template}"
|
||||
)
|
||||
return
|
||||
|
||||
if not replace_keywords:
|
||||
keywords.update(photo.keywords)
|
||||
|
||||
verbose(
|
||||
f"Setting [i]keywords[/] to {', '.join(f'[bold]{kw}[/]' for kw in keywords)}"
|
||||
)
|
||||
if not dry_run:
|
||||
ps_photo = photoscript_photo(photo)
|
||||
ps_photo.keywords = list(keywords)
|
||||
|
||||
|
||||
def set_photo_location(
|
||||
photo: osxphotos.PhotoInfo, location: tuple[float, float], dry_run: bool
|
||||
):
|
||||
"""Set photo location"""
|
||||
if not location or location[0] is None or location[1] is None:
|
||||
return
|
||||
|
||||
latitude, longitude = location
|
||||
verbose(
|
||||
f"Setting [i]location[/] to [num]{latitude:.6f}[/], [num]{longitude:.6f}[/]"
|
||||
)
|
||||
if not dry_run:
|
||||
ps_photo = photoscript_photo(photo)
|
||||
ps_photo.location = (latitude, longitude)
|
||||
@@ -9,19 +9,20 @@ import click
|
||||
|
||||
from osxphotos._constants import PROFILE_SORT_KEYS
|
||||
from osxphotos._version import __version__
|
||||
from osxphotos.platform import is_macos
|
||||
|
||||
from .about import about
|
||||
from .albums import albums
|
||||
from .common import DB_OPTION, JSON_OPTION, OSXPHOTOS_HIDDEN
|
||||
from .cli_params import DEBUG_OPTIONS, VERSION_OPTION
|
||||
from .common import OSXPHOTOS_HIDDEN
|
||||
from .debug_dump import debug_dump
|
||||
from .docs import docs
|
||||
from .docs import docs_command
|
||||
from .dump import dump
|
||||
from .exiftool_cli import exiftool
|
||||
from .export import export
|
||||
from .exportdb import exportdb
|
||||
from .grep import grep
|
||||
from .help import help
|
||||
from .import_cli import import_cli
|
||||
from .info import info
|
||||
from .install_uninstall_run import install, run, uninstall
|
||||
from .keywords import keywords
|
||||
@@ -29,18 +30,23 @@ from .labels import labels
|
||||
from .list import list_libraries
|
||||
from .orphans import orphans
|
||||
from .persons import persons
|
||||
from .photo_inspect import photo_inspect
|
||||
from .places import places
|
||||
from .query import query
|
||||
from .repl import repl
|
||||
from .snap_diff import diff, snap
|
||||
from .sync import sync
|
||||
from .theme import theme
|
||||
from .timewarp import timewarp
|
||||
from .tutorial import tutorial
|
||||
from .uuid import uuid
|
||||
from .version import version
|
||||
from .common import DEBUG_OPTIONS
|
||||
|
||||
if is_macos:
|
||||
from .add_locations import add_locations
|
||||
from .batch_edit import batch_edit
|
||||
from .import_cli import import_cli
|
||||
from .photo_inspect import photo_inspect
|
||||
from .show_command import show
|
||||
from .sync import sync
|
||||
from .timewarp import timewarp
|
||||
from .uuid import uuid
|
||||
|
||||
|
||||
# Click CLI object & context settings
|
||||
@@ -55,9 +61,7 @@ CTX_SETTINGS = dict(help_option_names=["-h", "--help"])
|
||||
|
||||
|
||||
@click.group(context_settings=CTX_SETTINGS)
|
||||
@click.version_option(__version__, "--version", "-v")
|
||||
@DB_OPTION
|
||||
@JSON_OPTION
|
||||
@VERSION_OPTION
|
||||
@DEBUG_OPTIONS
|
||||
@click.option(
|
||||
"--profile", is_flag=True, hidden=OSXPHOTOS_HIDDEN, help="Enable profiling"
|
||||
@@ -77,12 +81,12 @@ CTX_SETTINGS = dict(help_option_names=["-h", "--help"])
|
||||
"Default = 'cumulative'.",
|
||||
)
|
||||
@click.pass_context
|
||||
def cli_main(ctx, db, json_, profile, profile_sort, **kwargs):
|
||||
def cli_main(ctx, profile, profile_sort, **kwargs):
|
||||
"""osxphotos: the multi-tool for your Photos library"""
|
||||
# Note: kwargs is used to catch any debug options passed in
|
||||
# the debug options are handled in cli/__init__.py
|
||||
# before this function is called
|
||||
ctx.obj = CLI_Obj(db=db, json=json_, group=cli_main)
|
||||
ctx.obj = CLI_Obj(group=cli_main)
|
||||
if profile:
|
||||
click.echo("Profiling...")
|
||||
profile_sort = profile_sort or ["cumulative"]
|
||||
@@ -103,19 +107,18 @@ def cli_main(ctx, db, json_, profile, profile_sort, **kwargs):
|
||||
|
||||
|
||||
# install CLI commands
|
||||
for command in [
|
||||
commands = [
|
||||
about,
|
||||
albums,
|
||||
debug_dump,
|
||||
diff,
|
||||
docs,
|
||||
docs_command,
|
||||
dump,
|
||||
exiftool,
|
||||
export,
|
||||
exportdb,
|
||||
grep,
|
||||
help,
|
||||
import_cli,
|
||||
info,
|
||||
install,
|
||||
keywords,
|
||||
@@ -123,18 +126,28 @@ for command in [
|
||||
list_libraries,
|
||||
orphans,
|
||||
persons,
|
||||
photo_inspect,
|
||||
places,
|
||||
query,
|
||||
repl,
|
||||
run,
|
||||
snap,
|
||||
sync,
|
||||
theme,
|
||||
timewarp,
|
||||
tutorial,
|
||||
uninstall,
|
||||
uuid,
|
||||
version,
|
||||
]:
|
||||
]
|
||||
|
||||
if is_macos:
|
||||
commands += [
|
||||
add_locations,
|
||||
batch_edit,
|
||||
import_cli,
|
||||
photo_inspect,
|
||||
show,
|
||||
sync,
|
||||
timewarp,
|
||||
uuid,
|
||||
]
|
||||
|
||||
for command in commands:
|
||||
cli_main.add_command(command)
|
||||
|
||||
310
osxphotos/cli/cli_commands.py
Normal file
310
osxphotos/cli/cli_commands.py
Normal file
@@ -0,0 +1,310 @@
|
||||
"""Helper functions to make writing an osxphotos CLI tool easy.
|
||||
|
||||
Includes decorator to create an osxphotos query command to be run via `osxphotos run example.py`.
|
||||
|
||||
May also be run via `python example.py` if you have pip installed osxphotos
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import typing as t # match style used in Click source code
|
||||
|
||||
import click
|
||||
|
||||
from osxphotos.photosdb import PhotosDB
|
||||
from osxphotos.queryoptions import QueryOptions, query_options_from_kwargs
|
||||
from osxphotos.sqlitekvstore import SQLiteKVStore
|
||||
|
||||
from .cli_params import (
|
||||
_DB_PARAMETER,
|
||||
_QUERY_PARAMETERS_DICT,
|
||||
DB_OPTION,
|
||||
THEME_OPTION,
|
||||
TIMESTAMP_OPTION,
|
||||
VERBOSE_OPTION,
|
||||
)
|
||||
from .click_rich_echo import rich_click_echo as echo
|
||||
from .click_rich_echo import rich_echo_error as echo_error
|
||||
from .click_rich_echo import set_rich_theme
|
||||
from .color_themes import get_theme
|
||||
from .verbose import verbose, verbose_print
|
||||
|
||||
logger = logging.getLogger("osxphotos")
|
||||
|
||||
# ensure echo, echo_error are configured with correct theme
|
||||
set_rich_theme(get_theme())
|
||||
|
||||
__all__ = [
|
||||
"abort",
|
||||
"echo",
|
||||
"echo_error",
|
||||
"logger",
|
||||
"query_command",
|
||||
"selection_command",
|
||||
"verbose",
|
||||
]
|
||||
|
||||
|
||||
def abort(message: str, exit_code: int = 1):
|
||||
"""Abort with error message and exit code"""
|
||||
echo_error(f"[error]{message}[/]")
|
||||
sys.exit(exit_code)
|
||||
|
||||
|
||||
def config_verbose_callback(ctx: click.Context, param: click.Parameter, value: t.Any):
|
||||
"""Callback for --verbose option"""
|
||||
# calling verbose_print() will set the verbose level for the verbose() function
|
||||
theme = ctx.params.get("theme")
|
||||
timestamp = ctx.params.get("timestamp")
|
||||
verbose_print(verbose=value, timestamp=timestamp, theme=theme)
|
||||
return value
|
||||
|
||||
|
||||
def get_photos_for_query(ctx: click.Context):
|
||||
"""Return list of PhotoInfo objects for the photos matching the query options in ctx.params"""
|
||||
options = query_options_from_kwargs(**ctx.params)
|
||||
db = ctx.params.get("db")
|
||||
photosdb = PhotosDB(dbfile=db, verbose=verbose)
|
||||
return photosdb.query(options=options)
|
||||
|
||||
|
||||
def get_selected_photos(ctx: click.Context):
|
||||
"""Return list of PhotoInfo objects for the photos currently selected in Photos.app"""
|
||||
photosdb = PhotosDB(verbose=verbose)
|
||||
return photosdb.query(options=QueryOptions(selected=True))
|
||||
|
||||
|
||||
class QueryCommand(click.Command):
|
||||
"""
|
||||
Click command to create an osxphotos query command.
|
||||
|
||||
This class is used by the query_command decorator to create a click command
|
||||
that runs an osxphotos query. It will automatically add the query options as
|
||||
well as the --verbose, --timestamp, --theme, and --db options.
|
||||
"""
|
||||
|
||||
standalone_mode = False
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: t.Optional[str],
|
||||
context_settings: t.Optional[t.Dict[str, t.Any]] = None,
|
||||
callback: t.Optional[t.Callable[..., t.Any]] = None,
|
||||
params: t.Optional[t.List[click.Parameter]] = None,
|
||||
help: t.Optional[str] = None,
|
||||
epilog: t.Optional[str] = None,
|
||||
short_help: t.Optional[str] = None,
|
||||
options_metavar: t.Optional[str] = "[OPTIONS]",
|
||||
add_help_option: bool = True,
|
||||
no_args_is_help: bool = False,
|
||||
hidden: bool = False,
|
||||
deprecated: bool = False,
|
||||
) -> None:
|
||||
self.params = params or []
|
||||
self.params.append(
|
||||
click.Option(
|
||||
param_decls=["--verbose", "-V", "verbose_flag"],
|
||||
count=True,
|
||||
help="Print verbose output; may be specified multiple times for more verbose output.",
|
||||
callback=config_verbose_callback,
|
||||
)
|
||||
)
|
||||
self.params.append(
|
||||
click.Option(
|
||||
param_decls=["--timestamp"],
|
||||
is_flag=True,
|
||||
help="Add time stamp to verbose output",
|
||||
)
|
||||
)
|
||||
self.params.append(
|
||||
click.Option(
|
||||
param_decls=["--theme"],
|
||||
metavar="THEME",
|
||||
type=click.Choice(
|
||||
["dark", "light", "mono", "plain"], case_sensitive=False
|
||||
),
|
||||
help="Specify the color theme to use for output. "
|
||||
"Valid themes are 'dark', 'light', 'mono', and 'plain'. "
|
||||
"Defaults to 'dark' or 'light' depending on system dark mode setting.",
|
||||
)
|
||||
)
|
||||
self.params.append(_DB_PARAMETER)
|
||||
self.params.extend(_QUERY_PARAMETERS_DICT.values())
|
||||
|
||||
super().__init__(
|
||||
name,
|
||||
context_settings,
|
||||
callback,
|
||||
self.params,
|
||||
help,
|
||||
epilog,
|
||||
short_help,
|
||||
options_metavar,
|
||||
add_help_option,
|
||||
no_args_is_help,
|
||||
hidden,
|
||||
deprecated,
|
||||
)
|
||||
|
||||
def make_context(
|
||||
self,
|
||||
info_name: t.Optional[str],
|
||||
args: t.List[str],
|
||||
parent: t.Optional[click.Context] = None,
|
||||
**extra: t.Any,
|
||||
) -> click.Context:
|
||||
ctx = super().make_context(info_name, args, parent, **extra)
|
||||
ctx.obj = self
|
||||
photos = get_photos_for_query(ctx)
|
||||
ctx.params["photos"] = photos
|
||||
|
||||
# remove params handled by this class
|
||||
ctx.params.pop("verbose_flag")
|
||||
ctx.params.pop("timestamp")
|
||||
ctx.params.pop("theme")
|
||||
return ctx
|
||||
|
||||
|
||||
class SelectionCommand(click.Command):
|
||||
"""
|
||||
Click command to create an osxphotos selection command that runs on selected photos.
|
||||
|
||||
This class is used by the query_command decorator to create a click command
|
||||
that runs on currently selected photos.
|
||||
|
||||
The --verbose, --timestamp, --theme, and --db options will also be added to the command.
|
||||
"""
|
||||
|
||||
standalone_mode = False
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: t.Optional[str],
|
||||
context_settings: t.Optional[t.Dict[str, t.Any]] = None,
|
||||
callback: t.Optional[t.Callable[..., t.Any]] = None,
|
||||
params: t.Optional[t.List[click.Parameter]] = None,
|
||||
help: t.Optional[str] = None,
|
||||
epilog: t.Optional[str] = None,
|
||||
short_help: t.Optional[str] = None,
|
||||
options_metavar: t.Optional[str] = "[OPTIONS]",
|
||||
add_help_option: bool = True,
|
||||
no_args_is_help: bool = False,
|
||||
hidden: bool = False,
|
||||
deprecated: bool = False,
|
||||
) -> None:
|
||||
self.params = params or []
|
||||
self.params.append(
|
||||
click.Option(
|
||||
param_decls=["--verbose", "-V", "verbose_flag"],
|
||||
count=True,
|
||||
help="Print verbose output; may be specified multiple times for more verbose output.",
|
||||
callback=config_verbose_callback,
|
||||
)
|
||||
)
|
||||
self.params.append(
|
||||
click.Option(
|
||||
param_decls=["--timestamp"],
|
||||
is_flag=True,
|
||||
help="Add time stamp to verbose output",
|
||||
)
|
||||
)
|
||||
self.params.append(
|
||||
click.Option(
|
||||
param_decls=["--theme"],
|
||||
metavar="THEME",
|
||||
type=click.Choice(
|
||||
["dark", "light", "mono", "plain"], case_sensitive=False
|
||||
),
|
||||
help="Specify the color theme to use for output. "
|
||||
"Valid themes are 'dark', 'light', 'mono', and 'plain'. "
|
||||
"Defaults to 'dark' or 'light' depending on system dark mode setting.",
|
||||
)
|
||||
)
|
||||
self.params.append(
|
||||
click.Option(
|
||||
param_decls=["--library", "--db"],
|
||||
required=False,
|
||||
metavar="PHOTOS_LIBRARY_PATH",
|
||||
default=None,
|
||||
help=(
|
||||
"Specify Photos database path. "
|
||||
"Path to Photos library/database can be specified using either --db "
|
||||
"or directly as PHOTOS_LIBRARY positional argument. "
|
||||
"If neither --db or PHOTOS_LIBRARY provided, will attempt to find the library "
|
||||
"to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary"
|
||||
),
|
||||
type=click.Path(exists=True),
|
||||
)
|
||||
)
|
||||
super().__init__(
|
||||
name,
|
||||
context_settings,
|
||||
callback,
|
||||
self.params,
|
||||
help,
|
||||
epilog,
|
||||
short_help,
|
||||
options_metavar,
|
||||
add_help_option,
|
||||
no_args_is_help,
|
||||
hidden,
|
||||
deprecated,
|
||||
)
|
||||
|
||||
def make_context(
|
||||
self,
|
||||
info_name: t.Optional[str],
|
||||
args: t.List[str],
|
||||
parent: t.Optional[click.Context] = None,
|
||||
**extra: t.Any,
|
||||
) -> click.Context:
|
||||
ctx = super().make_context(info_name, args, parent, **extra)
|
||||
ctx.obj = self
|
||||
photos = get_selected_photos(ctx)
|
||||
ctx.params["photos"] = photos
|
||||
|
||||
# remove params handled by this class
|
||||
ctx.params.pop("verbose_flag")
|
||||
ctx.params.pop("timestamp")
|
||||
ctx.params.pop("theme")
|
||||
return ctx
|
||||
|
||||
|
||||
def query_command(name=None, cls=QueryCommand, **attrs):
|
||||
"""Decorator to create an osxphotos command to be run via `osxphotos run example.py`
|
||||
|
||||
The command will be passed a list of PhotoInfo objects for all photos in Photos
|
||||
matching the query options or all photos if no query options are specified.
|
||||
|
||||
The standard osxphotos query options will be added to the command.
|
||||
|
||||
The CLI will also be passed the following options:
|
||||
|
||||
--verbose
|
||||
--timestamp
|
||||
--theme
|
||||
--db
|
||||
"""
|
||||
if callable(name) and cls:
|
||||
return click.command(cls=cls, **attrs)(name)
|
||||
|
||||
return click.command(name, cls=cls, **attrs)
|
||||
|
||||
|
||||
def selection_command(name=None, cls=SelectionCommand, **attrs):
|
||||
"""Decorator to create an osxphotos command to be run via `osxphotos run example.py`
|
||||
|
||||
The command will be passed a list of PhotoInfo objects for all photos selected in Photos.
|
||||
The CLI will also be passed the following options:
|
||||
|
||||
--verbose
|
||||
--timestamp
|
||||
--theme
|
||||
--db
|
||||
"""
|
||||
if callable(name) and cls:
|
||||
return click.command(cls=cls, **attrs)(name)
|
||||
|
||||
return click.command(name, cls=cls, **attrs)
|
||||
779
osxphotos/cli/cli_params.py
Normal file
779
osxphotos/cli/cli_params.py
Normal file
@@ -0,0 +1,779 @@
|
||||
"""Common options & parameters for osxphotos CLI commands"""
|
||||
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import functools
|
||||
from textwrap import dedent
|
||||
from typing import Any, Callable
|
||||
|
||||
import click
|
||||
|
||||
from ..platform import is_macos
|
||||
from .common import OSXPHOTOS_HIDDEN, print_version
|
||||
from .param_types import *
|
||||
|
||||
__all__ = [
|
||||
"DB_ARGUMENT",
|
||||
"DB_OPTION",
|
||||
"DEBUG_OPTIONS",
|
||||
"DELETED_OPTIONS",
|
||||
"FIELD_OPTION",
|
||||
"JSON_OPTION",
|
||||
"QUERY_OPTIONS",
|
||||
"THEME_OPTION",
|
||||
"TIMESTAMP_OPTION",
|
||||
"VERBOSE_OPTION",
|
||||
"VERSION_OPTION",
|
||||
]
|
||||
|
||||
|
||||
def validate_selected(ctx, param, value):
|
||||
""" "Validate photos are actually selected when --selected is used"""
|
||||
|
||||
if not value:
|
||||
# --selected not used, just return
|
||||
return value
|
||||
|
||||
# imports here to avoid conflict with linux port
|
||||
# TODO: fix this once linux port is complete
|
||||
import photoscript
|
||||
from applescript import ScriptError
|
||||
|
||||
selection = None
|
||||
with contextlib.suppress(ScriptError):
|
||||
# ScriptError raised if selection made in edit mode or Smart Albums (on older versions of Photos)
|
||||
selection = photoscript.PhotosLibrary().selection
|
||||
|
||||
if not selection:
|
||||
click.echo(
|
||||
dedent(
|
||||
"""
|
||||
--selected option used but no photos selected in Photos.
|
||||
|
||||
To select photos in Photos use one of the following methods:
|
||||
|
||||
- Select a single photo: Click the photo, or press the arrow keys to quickly navigate to and select the photo.
|
||||
|
||||
- Select a group of adjacent photos in a day: Click the first photo, then hold down the Shift key while you click the last photo.
|
||||
You can also hold down Shift and press the arrow keys, or simply drag to enclose the photos within the selection rectangle.
|
||||
|
||||
- Select photos in a day that are not adjacent to each other: Hold down the Command key as you click each photo.
|
||||
|
||||
- Deselect specific photos: Hold down the Command key and click the photos you want to deselect.
|
||||
|
||||
- Deselect all photos: Click an empty space in the window (not a photo).
|
||||
"""
|
||||
),
|
||||
err=True,
|
||||
)
|
||||
ctx.exit(1)
|
||||
return value
|
||||
|
||||
|
||||
def _param_memo(f: Callable[..., Any], param: click.Parameter) -> None:
|
||||
"""Add param to the list of params for a click.Command
|
||||
This is directly from the click source code and
|
||||
the implementation is thus tightly coupled to click internals
|
||||
"""
|
||||
if isinstance(f, click.Command):
|
||||
f.params.append(param)
|
||||
else:
|
||||
if not hasattr(f, "__click_params__"):
|
||||
f.__click_params__ = [] # type: ignore
|
||||
|
||||
f.__click_params__.append(param) # type: ignore
|
||||
|
||||
|
||||
def make_click_option_decorator(*params: click.Parameter) -> Callable[..., Any]:
|
||||
"""Make a decorator for a click option from one or more click Parameter objects"""
|
||||
|
||||
def decorator(wrapped=None) -> Callable[..., Any]:
|
||||
"""Function decorator to add option to a click command.
|
||||
|
||||
Args:
|
||||
wrapped: function to decorate (this is normally passed automatically
|
||||
"""
|
||||
|
||||
if wrapped is None:
|
||||
return decorator
|
||||
|
||||
def _add_options(wrapped):
|
||||
"""Add query options to wrapped function"""
|
||||
for param in params:
|
||||
_param_memo(wrapped, param)
|
||||
return wrapped
|
||||
|
||||
return _add_options(wrapped)
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
VERSION_CHECK_OPTION = click.option("--no-version-check", required=False, is_flag=True)
|
||||
|
||||
_DB_PARAMETER = click.Option(
|
||||
["--library", "--db", "db"],
|
||||
required=False,
|
||||
metavar="PHOTOS_LIBRARY_PATH",
|
||||
default=None,
|
||||
help=(
|
||||
"Specify path to Photos library. "
|
||||
"If not provided, will attempt to find the library to use in the following order: "
|
||||
"1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary"
|
||||
),
|
||||
type=click.Path(exists=True),
|
||||
)
|
||||
|
||||
DB_OPTION = make_click_option_decorator(_DB_PARAMETER)
|
||||
|
||||
DB_ARGUMENT = click.argument(
|
||||
"photos_library",
|
||||
nargs=-1,
|
||||
type=DeprecatedPath(
|
||||
exists=True,
|
||||
deprecation_warning="The PHOTOS_LIBRARY argument is deprecated and "
|
||||
"will be removed in a future version of osxphotos. "
|
||||
"Use --library instead to specify the Photos Library path.",
|
||||
),
|
||||
)
|
||||
|
||||
_JSON_PARAMETER = click.Option(
|
||||
["--json", "json_"],
|
||||
required=False,
|
||||
is_flag=True,
|
||||
default=False,
|
||||
help="Print output in JSON format.",
|
||||
)
|
||||
|
||||
JSON_OPTION = make_click_option_decorator(_JSON_PARAMETER)
|
||||
|
||||
_FIELD_PARAMETER = click.Option(
|
||||
["--field", "-f"],
|
||||
metavar="FIELD TEMPLATE",
|
||||
multiple=True,
|
||||
nargs=2,
|
||||
help="Output only specified custom fields. "
|
||||
"FIELD is the name of the field and TEMPLATE is the template to use as the field value. "
|
||||
"May be repeated to output multiple fields. "
|
||||
"For example, to output photo uuid, name, and title: "
|
||||
'`--field uuid "{uuid}" --field name "{original_name}" --field title "{title}"`.',
|
||||
)
|
||||
|
||||
FIELD_OPTION = make_click_option_decorator(_FIELD_PARAMETER)
|
||||
|
||||
_DELETED_PARAMETERS = [
|
||||
click.Option(
|
||||
["--deleted"],
|
||||
is_flag=True,
|
||||
help="Include photos from the 'Recently Deleted' folder.",
|
||||
),
|
||||
click.Option(
|
||||
["--deleted-only"],
|
||||
is_flag=True,
|
||||
help="Include only photos from the 'Recently Deleted' folder.",
|
||||
),
|
||||
]
|
||||
|
||||
DELETED_OPTIONS = make_click_option_decorator(*_DELETED_PARAMETERS)
|
||||
|
||||
# The following are used by the query command and by
|
||||
# QUERY_OPTIONS to add the query options to other commands
|
||||
# To add new query options, add them to _QUERY_OPTIONS as
|
||||
# a click.Option, add them to osxphotos/photosdb/photosdb.py::PhotosDB.query(),
|
||||
# and to osxphotos/query_options.py::QueryOptions
|
||||
_QUERY_PARAMETERS_DICT = {
|
||||
"--keyword": click.Option(
|
||||
["--keyword"],
|
||||
metavar="KEYWORD",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for photos with keyword KEYWORD. "
|
||||
'If more than one keyword, treated as "OR", e.g. find photos matching any keyword',
|
||||
),
|
||||
"--no-keyword": click.Option(
|
||||
["--no-keyword"],
|
||||
is_flag=True,
|
||||
help="Search for photos with no keyword.",
|
||||
),
|
||||
"--person": click.Option(
|
||||
["--person"],
|
||||
metavar="PERSON",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for photos with person PERSON. "
|
||||
'If more than one person, treated as "OR", e.g. find photos matching any person',
|
||||
),
|
||||
"--album": click.Option(
|
||||
["--album"],
|
||||
metavar="ALBUM",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for photos in album ALBUM. "
|
||||
'If more than one album, treated as "OR", e.g. find photos matching any album',
|
||||
),
|
||||
"--folder": click.Option(
|
||||
["--folder"],
|
||||
metavar="FOLDER",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for photos in an album in folder FOLDER. "
|
||||
'If more than one folder, treated as "OR", e.g. find photos in any FOLDER. '
|
||||
"Only searches top level folders (e.g. does not look at subfolders)",
|
||||
),
|
||||
"--name": click.Option(
|
||||
["--name"],
|
||||
metavar="FILENAME",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for photos with filename matching FILENAME. "
|
||||
'If more than one --name options is specified, they are treated as "OR", '
|
||||
"e.g. find photos matching any FILENAME. ",
|
||||
),
|
||||
"--uuid": click.Option(
|
||||
["--uuid"],
|
||||
metavar="UUID",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for photos with UUID(s). "
|
||||
"May be repeated to include multiple UUIDs.",
|
||||
),
|
||||
"--uuid-from-file": click.Option(
|
||||
["--uuid-from-file"],
|
||||
metavar="FILE",
|
||||
default=None,
|
||||
multiple=False,
|
||||
help="Search for photos with UUID(s) loaded from FILE. "
|
||||
"Format is a single UUID per line. Lines preceded with # are ignored. "
|
||||
"If FILE is '-', read UUIDs from stdin.",
|
||||
type=PathOrStdin(exists=True),
|
||||
),
|
||||
"--title": click.Option(
|
||||
["--title"],
|
||||
metavar="TITLE",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for TITLE in title of photo.",
|
||||
),
|
||||
"--no-title": click.Option(
|
||||
["--no-title"], is_flag=True, help="Search for photos with no title."
|
||||
),
|
||||
"--description": click.Option(
|
||||
["--description"],
|
||||
metavar="DESC",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for DESC in description of photo.",
|
||||
),
|
||||
"--no-description": click.Option(
|
||||
["--no-description"],
|
||||
is_flag=True,
|
||||
help="Search for photos with no description.",
|
||||
),
|
||||
"--place": click.Option(
|
||||
["--place"],
|
||||
metavar="PLACE",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for PLACE in photo's reverse geolocation info",
|
||||
),
|
||||
"--no-place": click.Option(
|
||||
["--no-place"],
|
||||
is_flag=True,
|
||||
help="Search for photos with no associated place name info (no reverse geolocation info)",
|
||||
),
|
||||
"--location": click.Option(
|
||||
["--location"],
|
||||
is_flag=True,
|
||||
help="Search for photos with associated location info (e.g. GPS coordinates)",
|
||||
),
|
||||
"--no-location": click.Option(
|
||||
["--no-location"],
|
||||
is_flag=True,
|
||||
help="Search for photos with no associated location info (e.g. no GPS coordinates)",
|
||||
),
|
||||
"--label": click.Option(
|
||||
["--label"],
|
||||
metavar="LABEL",
|
||||
multiple=True,
|
||||
help="Search for photos with image classification label LABEL (Photos 5+ only). "
|
||||
'If more than one label, treated as "OR", e.g. find photos matching any label',
|
||||
),
|
||||
"--uti": click.Option(
|
||||
["--uti"],
|
||||
metavar="UTI",
|
||||
default=None,
|
||||
multiple=False,
|
||||
help="Search for photos whose uniform type identifier (UTI) matches UTI",
|
||||
),
|
||||
"--ignore_case": click.Option(
|
||||
["-i", "--ignore-case"],
|
||||
is_flag=True,
|
||||
help="Case insensitive search for title, description, place, keyword, person, or album.",
|
||||
),
|
||||
"--edited": click.Option(
|
||||
["--edited"],
|
||||
is_flag=True,
|
||||
help="Search for photos that have been edited.",
|
||||
),
|
||||
"--not-edited": click.Option(
|
||||
["--not-edited"],
|
||||
is_flag=True,
|
||||
help="Search for photos that have not been edited.",
|
||||
),
|
||||
"--external-edit": click.Option(
|
||||
["--external-edit"],
|
||||
is_flag=True,
|
||||
help="Search for photos edited in external editor.",
|
||||
),
|
||||
"--favorite": click.Option(
|
||||
["--favorite"], is_flag=True, help="Search for photos marked favorite."
|
||||
),
|
||||
"--not-favorite": click.Option(
|
||||
["--not-favorite"],
|
||||
is_flag=True,
|
||||
help="Search for photos not marked favorite.",
|
||||
),
|
||||
"--hidden": click.Option(
|
||||
["--hidden"], is_flag=True, help="Search for photos marked hidden."
|
||||
),
|
||||
"--not-hidden": click.Option(
|
||||
["--not-hidden"],
|
||||
is_flag=True,
|
||||
help="Search for photos not marked hidden.",
|
||||
),
|
||||
"--shared": click.Option(
|
||||
["--shared"],
|
||||
is_flag=True,
|
||||
help="Search for photos in shared iCloud album (Photos 5+ only).",
|
||||
),
|
||||
"--not-shared": click.Option(
|
||||
["--not-shared"],
|
||||
is_flag=True,
|
||||
help="Search for photos not in shared iCloud album (Photos 5+ only).",
|
||||
),
|
||||
"--burst": click.Option(
|
||||
["--burst"],
|
||||
is_flag=True,
|
||||
help="Search for photos that were taken in a burst.",
|
||||
),
|
||||
"--not-burst": click.Option(
|
||||
["--not-burst"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not part of a burst.",
|
||||
),
|
||||
"--live": click.Option(
|
||||
["--live"], is_flag=True, help="Search for Apple live photos"
|
||||
),
|
||||
"--not-live": click.Option(
|
||||
["--not-live"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not Apple live photos.",
|
||||
),
|
||||
"--portrait": click.Option(
|
||||
["--portrait"],
|
||||
is_flag=True,
|
||||
help="Search for Apple portrait mode photos.",
|
||||
),
|
||||
"--not-portrait": click.Option(
|
||||
["--not-portrait"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not Apple portrait mode photos.",
|
||||
),
|
||||
"--screenshot": click.Option(
|
||||
["--screenshot"], is_flag=True, help="Search for screenshot photos."
|
||||
),
|
||||
"--not-screenshot": click.Option(
|
||||
["--not-screenshot"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not screenshot photos.",
|
||||
),
|
||||
"--slow-mo": click.Option(
|
||||
["--slow-mo"], is_flag=True, help="Search for slow motion videos."
|
||||
),
|
||||
"--not-slow-mo": click.Option(
|
||||
["--not-slow-mo"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not slow motion videos.",
|
||||
),
|
||||
"--time-lapse": click.Option(
|
||||
["--time-lapse"], is_flag=True, help="Search for time lapse videos."
|
||||
),
|
||||
"--not-time-lapse": click.Option(
|
||||
["--not-time-lapse"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not time lapse videos.",
|
||||
),
|
||||
"--hdr": click.Option(
|
||||
["--hdr"],
|
||||
is_flag=True,
|
||||
help="Search for high dynamic range (HDR) photos.",
|
||||
),
|
||||
"--not-hdr": click.Option(
|
||||
["--not-hdr"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not HDR photos.",
|
||||
),
|
||||
"--selfie": click.Option(
|
||||
["--selfie"],
|
||||
is_flag=True,
|
||||
help="Search for selfies (photos taken with front-facing cameras).",
|
||||
),
|
||||
"--not-selfie": click.Option(
|
||||
["--not-selfie"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not selfies.",
|
||||
),
|
||||
"--panorama": click.Option(
|
||||
["--panorama"], is_flag=True, help="Search for panorama photos."
|
||||
),
|
||||
"--not-panorama": click.Option(
|
||||
["--not-panorama"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not panoramas.",
|
||||
),
|
||||
"--has-raw": click.Option(
|
||||
["--has-raw"],
|
||||
is_flag=True,
|
||||
help="Search for photos with both a jpeg and raw version",
|
||||
),
|
||||
"--only-movies": click.Option(
|
||||
["--only-movies"],
|
||||
is_flag=True,
|
||||
help="Search only for movies (default searches both images and movies).",
|
||||
),
|
||||
"--only-photos": click.Option(
|
||||
["--only-photos"],
|
||||
is_flag=True,
|
||||
help="Search only for photos/images (default searches both images and movies).",
|
||||
),
|
||||
"--from-date": click.Option(
|
||||
["--from-date"],
|
||||
help="Search by item start date, e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).",
|
||||
type=DateTimeISO8601(),
|
||||
),
|
||||
"--to-date": click.Option(
|
||||
["--to-date"],
|
||||
help="Search by item end date, e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).",
|
||||
type=DateTimeISO8601(),
|
||||
),
|
||||
"--from-time": click.Option(
|
||||
["--from-time"],
|
||||
help="Search by item start time of day, e.g. 12:00, or 12:00:00.",
|
||||
type=TimeISO8601(),
|
||||
),
|
||||
"--to-time": click.Option(
|
||||
["--to-time"],
|
||||
help="Search by item end time of day, e.g. 12:00 or 12:00:00.",
|
||||
type=TimeISO8601(),
|
||||
),
|
||||
"--year": click.Option(
|
||||
["--year"],
|
||||
metavar="YEAR",
|
||||
help="Search for items from a specific year, e.g. --year 2022 to find all photos from the year 2022. "
|
||||
"May be repeated to search multiple years.",
|
||||
multiple=True,
|
||||
type=int,
|
||||
),
|
||||
"--added-before": click.Option(
|
||||
["--added-before"],
|
||||
metavar="DATE",
|
||||
help="Search for items added to the library before a specific date/time, "
|
||||
"e.g. --added-before e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).",
|
||||
type=DateTimeISO8601(),
|
||||
),
|
||||
"--added-after": click.Option(
|
||||
["--added-after"],
|
||||
metavar="DATE",
|
||||
help="Search for items added to the libray after a specific date/time, "
|
||||
"e.g. --added-after e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).",
|
||||
type=DateTimeISO8601(),
|
||||
),
|
||||
"--added-in-last": click.Option(
|
||||
["--added-in-last"],
|
||||
metavar="TIME_DELTA",
|
||||
help="Search for items added to the library in the last TIME_DELTA, "
|
||||
"where TIME_DELTA is a string like "
|
||||
"'12 hrs', '1 day', '1d', '1 week', '2weeks', '1 month', '1 year'. "
|
||||
"for example, `--added-in-last 7d` and `--added-in-last '1 week'` are equivalent. "
|
||||
"months are assumed to be 30 days and years are assumed to be 365 days. "
|
||||
"Common English abbreviations are accepted, e.g. d, day, days or m, min, minutes.",
|
||||
type=TimeOffset(),
|
||||
),
|
||||
"--has-comment": click.Option(
|
||||
["--has-comment"],
|
||||
is_flag=True,
|
||||
help="Search for photos that have comments.",
|
||||
),
|
||||
"--no-comment": click.Option(
|
||||
["--no-comment"],
|
||||
is_flag=True,
|
||||
help="Search for photos with no comments.",
|
||||
),
|
||||
"--has-likes": click.Option(
|
||||
["--has-likes"], is_flag=True, help="Search for photos that have likes."
|
||||
),
|
||||
"--no-likes": click.Option(
|
||||
["--no-likes"], is_flag=True, help="Search for photos with no likes."
|
||||
),
|
||||
"--is-reference": click.Option(
|
||||
["--is-reference"],
|
||||
is_flag=True,
|
||||
help="Search for photos that were imported as referenced files (not copied into Photos library).",
|
||||
),
|
||||
"--not-reference": click.Option(
|
||||
["--not-reference"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not references, that is, they were copied into the Photos library "
|
||||
"and are managed by Photos.",
|
||||
),
|
||||
"--in-album": click.Option(
|
||||
["--in-album"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are in one or more albums.",
|
||||
),
|
||||
"--not-in-album": click.Option(
|
||||
["--not-in-album"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not in any albums.",
|
||||
),
|
||||
"--duplicate": click.Option(
|
||||
["--duplicate"],
|
||||
is_flag=True,
|
||||
help="Search for photos with possible duplicates. osxphotos will compare signatures of photos, "
|
||||
"evaluating date created, size, height, width, and edited status to find *possible* duplicates. "
|
||||
"This does not compare images byte-for-byte nor compare hashes but should find photos imported multiple "
|
||||
"times or duplicated within Photos.",
|
||||
),
|
||||
"--min-size": click.Option(
|
||||
["--min-size"],
|
||||
metavar="SIZE",
|
||||
type=BitMathSize(),
|
||||
help="Search for photos with size >= SIZE bytes. "
|
||||
"The size evaluated is the photo's original size (when imported to Photos). "
|
||||
"Size may be specified as integer bytes or using SI or NIST units. "
|
||||
"For example, the following are all valid and equivalent sizes: '1048576' '1.048576MB', '1 MiB'.",
|
||||
),
|
||||
"--max-size": click.Option(
|
||||
["--max-size"],
|
||||
metavar="SIZE",
|
||||
type=BitMathSize(),
|
||||
help="Search for photos with size <= SIZE bytes. "
|
||||
"The size evaluated is the photo's original size (when imported to Photos). "
|
||||
"Size may be specified as integer bytes or using SI or NIST units. "
|
||||
"For example, the following are all valid and equivalent sizes: '1048576' '1.048576MB', '1 MiB'.",
|
||||
),
|
||||
"--missing": click.Option(
|
||||
["--missing"], is_flag=True, help="Search for photos missing from disk."
|
||||
),
|
||||
"--not-missing": click.Option(
|
||||
["--not-missing"],
|
||||
is_flag=True,
|
||||
help="Search for photos present on disk (e.g. not missing).",
|
||||
),
|
||||
"--cloudasset": click.Option(
|
||||
["--cloudasset"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are part of an iCloud library",
|
||||
),
|
||||
"--not-cloudasset": click.Option(
|
||||
["--not-cloudasset"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not part of an iCloud library",
|
||||
),
|
||||
"--incloud": click.Option(
|
||||
["--incloud"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are in iCloud (have been synched)",
|
||||
),
|
||||
"--not-incloud": click.Option(
|
||||
["--not-incloud"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not in iCloud (have not been synched)",
|
||||
),
|
||||
"--syndicated": click.Option(
|
||||
["--syndicated"],
|
||||
is_flag=True,
|
||||
help="Search for photos that have been shared via syndication ('Shared with You' album via Messages, etc.)",
|
||||
),
|
||||
"--not-syndicated": click.Option(
|
||||
["--not-syndicated"],
|
||||
is_flag=True,
|
||||
help="Search for photos that have not been shared via syndication ('Shared with You' album via Messages, etc.)",
|
||||
),
|
||||
"--saved-to-library": click.Option(
|
||||
["--saved-to-library"],
|
||||
is_flag=True,
|
||||
help="Search for syndicated photos that have saved to the library",
|
||||
),
|
||||
"--not-saved-to-library": click.Option(
|
||||
["--not-saved-to-library"],
|
||||
is_flag=True,
|
||||
help="Search for syndicated photos that have not saved to the library",
|
||||
),
|
||||
"--shared-moment": click.Option(
|
||||
["--shared-moment"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are part of a shared moment",
|
||||
),
|
||||
"--not-shared-moment": click.Option(
|
||||
["--not-shared-moment"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not part of a shared moment",
|
||||
),
|
||||
"--shared-library": click.Option(
|
||||
["--shared-library"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are part of a shared library",
|
||||
),
|
||||
"--not-shared-library": click.Option(
|
||||
["--not-shared-library"],
|
||||
is_flag=True,
|
||||
help="Search for photos that are not part of a shared library",
|
||||
),
|
||||
"--regex": click.Option(
|
||||
["--regex"],
|
||||
metavar="REGEX TEMPLATE",
|
||||
nargs=2,
|
||||
multiple=True,
|
||||
help="Search for photos where TEMPLATE matches regular expression REGEX. "
|
||||
"For example, to find photos in an album that begins with 'Beach': '--regex \"^Beach\" \"{album}\"'. "
|
||||
"You may specify more than one regular expression match by repeating '--regex' with different arguments.",
|
||||
),
|
||||
"--selected": click.Option(
|
||||
["--selected"],
|
||||
is_flag=True,
|
||||
help="Filter for photos that are currently selected in Photos.",
|
||||
callback=validate_selected,
|
||||
),
|
||||
"--exif": click.Option(
|
||||
["--exif"],
|
||||
metavar="EXIF_TAG VALUE",
|
||||
nargs=2,
|
||||
multiple=True,
|
||||
help="Search for photos where EXIF_TAG exists in photo's EXIF data and contains VALUE. "
|
||||
"For example, to find photos created by Adobe Photoshop: `--exif Software 'Adobe Photoshop' `"
|
||||
"or to find all photos shot on a Canon camera: `--exif Make Canon`. "
|
||||
"EXIF_TAG can be any valid exiftool tag, with or without group name, e.g. `EXIF:Make` or `Make`. "
|
||||
"To use --exif, exiftool must be installed and in the path.",
|
||||
),
|
||||
"--query-eval": click.Option(
|
||||
["--query-eval"],
|
||||
metavar="CRITERIA",
|
||||
multiple=True,
|
||||
help="Evaluate CRITERIA to filter photos. "
|
||||
"CRITERIA will be evaluated in context of the following python list comprehension: "
|
||||
"`photos = [photo for photo in photos if CRITERIA]` "
|
||||
"where photo represents a PhotoInfo object. "
|
||||
"For example: `--query-eval photo.favorite` returns all photos that have been "
|
||||
"favorited and is equivalent to --favorite. "
|
||||
"You may specify more than one CRITERIA by using --query-eval multiple times. "
|
||||
"CRITERIA must be a valid python expression. "
|
||||
"See https://rhettbull.github.io/osxphotos/ for additional documentation on the PhotoInfo class.",
|
||||
),
|
||||
"--query-function": click.Option(
|
||||
["--query-function"],
|
||||
metavar="filename.py::function",
|
||||
multiple=True,
|
||||
type=FunctionCall(),
|
||||
help="Run function to filter photos. Use this in format: --query-function filename.py::function where filename.py is a python "
|
||||
+ "file you've created and function is the name of the function in the python file you want to call. "
|
||||
+ "Your function will be passed a list of PhotoInfo objects and is expected to return a filtered list of PhotoInfo objects. "
|
||||
+ "You may use more than one function by repeating the --query-function option with a different value. "
|
||||
+ "Your query function will be called after all other query options have been evaluated. "
|
||||
+ "See https://github.com/RhetTbull/osxphotos/blob/master/examples/query_function.py for example of how to use this option.",
|
||||
),
|
||||
}
|
||||
|
||||
if not is_macos:
|
||||
del _QUERY_PARAMETERS_DICT["--selected"]
|
||||
|
||||
|
||||
def QUERY_OPTIONS(
|
||||
wrapped=None, *, exclude: list[str] | None = None
|
||||
) -> Callable[..., Any]:
|
||||
"""Function decorator to add query options to a click command.
|
||||
|
||||
Args:
|
||||
wrapped: function to decorate (this is normally passed automatically
|
||||
exclude: list of query options to exclude from the command, for example `exclude=["--shared"]
|
||||
"""
|
||||
if wrapped is None:
|
||||
return functools.partial(QUERY_OPTIONS, exclude=exclude)
|
||||
|
||||
exclude = exclude or []
|
||||
|
||||
def _add_options(wrapped):
|
||||
"""Add query options to wrapped function"""
|
||||
for option in reversed(_QUERY_PARAMETERS_DICT.keys()):
|
||||
if option in exclude:
|
||||
continue
|
||||
click_opt = _QUERY_PARAMETERS_DICT[option]
|
||||
_param_memo(wrapped, click_opt)
|
||||
return wrapped
|
||||
|
||||
return _add_options(wrapped)
|
||||
|
||||
|
||||
_DEBUG_PARAMETERS = [
|
||||
click.Option(
|
||||
["--debug"],
|
||||
is_flag=True,
|
||||
help="Enable debug output.",
|
||||
hidden=OSXPHOTOS_HIDDEN,
|
||||
),
|
||||
click.Option(
|
||||
["--watch"],
|
||||
metavar="MODULE::NAME",
|
||||
multiple=True,
|
||||
help="Watch function or method calls. The function to watch must be in the form "
|
||||
"MODULE::NAME where MODULE is the module path and NAME is the function or method name "
|
||||
"contained in the module. For example, to watch all calls to FileUtil.copy() which is in "
|
||||
"osxphotos.fileutil, use: "
|
||||
"'--watch osxphotos.fileutil::FileUtil.copy'. More than one --watch option can be specified.",
|
||||
hidden=OSXPHOTOS_HIDDEN,
|
||||
),
|
||||
click.Option(
|
||||
["--breakpoint"],
|
||||
metavar="MODULE::NAME",
|
||||
multiple=True,
|
||||
help="Add breakpoint to function calls. The function to watch must be in the form "
|
||||
"MODULE::NAME where MODULE is the module path and NAME is the function or method name "
|
||||
"contained in the module. For example, to set a breakpoint for calls to "
|
||||
"FileUtil.copy() which is in osxphotos.fileutil, use: "
|
||||
"'--breakpoint osxphotos.fileutil::FileUtil.copy'. More than one --breakpoint option can be specified.",
|
||||
hidden=OSXPHOTOS_HIDDEN,
|
||||
),
|
||||
]
|
||||
DEBUG_OPTIONS = make_click_option_decorator(*_DEBUG_PARAMETERS)
|
||||
|
||||
_THEME_PARAMETER = click.Option(
|
||||
["--theme"],
|
||||
metavar="THEME",
|
||||
type=click.Choice(["dark", "light", "mono", "plain"], case_sensitive=False),
|
||||
help="Specify the color theme to use for output. "
|
||||
"Valid themes are 'dark', 'light', 'mono', and 'plain'. "
|
||||
"Defaults to 'dark' or 'light' depending on system dark mode setting.",
|
||||
)
|
||||
THEME_OPTION = make_click_option_decorator(_THEME_PARAMETER)
|
||||
|
||||
_VERBOSE_PARAMETER = click.Option(
|
||||
["--verbose", "-V", "verbose_flag"],
|
||||
count=True,
|
||||
help="Print verbose output; may be specified multiple times for more verbose output.",
|
||||
)
|
||||
VERBOSE_OPTION = make_click_option_decorator(_VERBOSE_PARAMETER)
|
||||
|
||||
_TIMESTAMP_PARAMETER = click.Option(
|
||||
["--timestamp"], is_flag=True, help="Add time stamp to verbose output"
|
||||
)
|
||||
TIMESTAMP_OPTION = make_click_option_decorator(_TIMESTAMP_PARAMETER)
|
||||
|
||||
_VERSION_PARAMETER = click.Option(
|
||||
["--version", "-v", "_version_flag"],
|
||||
is_flag=True,
|
||||
help="Show the version and exit.",
|
||||
callback=print_version,
|
||||
)
|
||||
|
||||
VERSION_OPTION = make_click_option_decorator(_VERSION_PARAMETER)
|
||||
@@ -119,7 +119,9 @@ def rich_echo(
|
||||
# if not outputting to terminal, use a huge width to avoid wrapping
|
||||
# otherwise tests fail
|
||||
width = 10_000
|
||||
console = get_rich_console() or Console(theme=theme, width=width)
|
||||
console = get_rich_console() or Console(
|
||||
theme=theme or get_rich_theme(), width=width
|
||||
)
|
||||
if markdown:
|
||||
message = Markdown(message)
|
||||
# Markdown always adds a new line so disable unless explicitly specified
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
"""Globals and constants use by the CLI commands"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import os
|
||||
import pathlib
|
||||
import platform
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
import click
|
||||
@@ -11,13 +13,11 @@ from packaging import version
|
||||
from xdg import xdg_config_home, xdg_data_home
|
||||
|
||||
import osxphotos
|
||||
from osxphotos import QueryOptions
|
||||
from osxphotos._constants import APP_NAME
|
||||
from osxphotos._version import __version__
|
||||
from osxphotos.platform import get_macos_version
|
||||
from osxphotos.utils import get_latest_version
|
||||
|
||||
from .param_types import *
|
||||
|
||||
# used to show/hide hidden commands
|
||||
OSXPHOTOS_HIDDEN = not bool(os.getenv("OSXPHOTOS_SHOW_HIDDEN", default=False))
|
||||
|
||||
@@ -33,28 +33,12 @@ CLI_COLOR_WARNING = "yellow"
|
||||
__all__ = [
|
||||
"CLI_COLOR_ERROR",
|
||||
"CLI_COLOR_WARNING",
|
||||
"DB_ARGUMENT",
|
||||
"DB_OPTION",
|
||||
"DEBUG_OPTIONS",
|
||||
"DELETED_OPTIONS",
|
||||
"FIELD_OPTION",
|
||||
"JSON_OPTION",
|
||||
"QUERY_OPTIONS",
|
||||
"THEME_OPTION",
|
||||
"get_photos_db",
|
||||
"load_uuid_from_file",
|
||||
"noop",
|
||||
"query_options_from_kwargs",
|
||||
"time_stamp",
|
||||
]
|
||||
|
||||
|
||||
class IncompatibleQueryOptions(Exception):
|
||||
"""Incompatible query options"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def noop(*args, **kwargs):
|
||||
"""no-op function"""
|
||||
pass
|
||||
@@ -98,550 +82,6 @@ def get_photos_db(*db_options):
|
||||
return None
|
||||
|
||||
|
||||
VERSION_CHECK_OPTION = click.option("--no-version-check", required=False, is_flag=True)
|
||||
|
||||
DB_OPTION = click.option(
|
||||
"--db",
|
||||
required=False,
|
||||
metavar="PHOTOS_LIBRARY_PATH",
|
||||
default=None,
|
||||
help=(
|
||||
"Specify Photos database path. "
|
||||
"Path to Photos library/database can be specified using either --db "
|
||||
"or directly as PHOTOS_LIBRARY positional argument. "
|
||||
"If neither --db or PHOTOS_LIBRARY provided, will attempt to find the library "
|
||||
"to use in the following order: 1. last opened library, 2. system library, 3. ~/Pictures/Photos Library.photoslibrary"
|
||||
),
|
||||
type=click.Path(exists=True),
|
||||
)
|
||||
|
||||
DB_ARGUMENT = click.argument("photos_library", nargs=-1, type=click.Path(exists=True))
|
||||
|
||||
JSON_OPTION = click.option(
|
||||
"--json",
|
||||
"json_",
|
||||
required=False,
|
||||
is_flag=True,
|
||||
default=False,
|
||||
help="Print output in JSON format.",
|
||||
)
|
||||
|
||||
FIELD_OPTION = click.option(
|
||||
"--field",
|
||||
"-f",
|
||||
metavar="FIELD TEMPLATE",
|
||||
multiple=True,
|
||||
nargs=2,
|
||||
help="Output only specified custom fields. "
|
||||
"FIELD is the name of the field and TEMPLATE is the template to use as the field value. "
|
||||
"May be repeated to output multiple fields. "
|
||||
"For example, to output photo uuid, name, and title: "
|
||||
'`--field uuid "{uuid}" --field name "{original_name}" --field title "{title}"`.',
|
||||
)
|
||||
|
||||
|
||||
def DELETED_OPTIONS(f):
|
||||
o = click.option
|
||||
options = [
|
||||
o(
|
||||
"--deleted",
|
||||
is_flag=True,
|
||||
help="Include photos from the 'Recently Deleted' folder.",
|
||||
),
|
||||
o(
|
||||
"--deleted-only",
|
||||
is_flag=True,
|
||||
help="Include only photos from the 'Recently Deleted' folder.",
|
||||
),
|
||||
]
|
||||
for o in options[::-1]:
|
||||
f = o(f)
|
||||
return f
|
||||
|
||||
|
||||
def QUERY_OPTIONS(f):
|
||||
o = click.option
|
||||
options = [
|
||||
o(
|
||||
"--keyword",
|
||||
metavar="KEYWORD",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for photos with keyword KEYWORD. "
|
||||
'If more than one keyword, treated as "OR", e.g. find photos matching any keyword',
|
||||
),
|
||||
o(
|
||||
"--no-keyword",
|
||||
is_flag=True,
|
||||
help="Search for photos with no keyword.",
|
||||
),
|
||||
o(
|
||||
"--person",
|
||||
metavar="PERSON",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for photos with person PERSON. "
|
||||
'If more than one person, treated as "OR", e.g. find photos matching any person',
|
||||
),
|
||||
o(
|
||||
"--album",
|
||||
metavar="ALBUM",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for photos in album ALBUM. "
|
||||
'If more than one album, treated as "OR", e.g. find photos matching any album',
|
||||
),
|
||||
o(
|
||||
"--folder",
|
||||
metavar="FOLDER",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for photos in an album in folder FOLDER. "
|
||||
'If more than one folder, treated as "OR", e.g. find photos in any FOLDER. '
|
||||
"Only searches top level folders (e.g. does not look at subfolders)",
|
||||
),
|
||||
o(
|
||||
"--name",
|
||||
metavar="FILENAME",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for photos with filename matching FILENAME. "
|
||||
'If more than one --name options is specified, they are treated as "OR", '
|
||||
"e.g. find photos matching any FILENAME. ",
|
||||
),
|
||||
o(
|
||||
"--uuid",
|
||||
metavar="UUID",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for photos with UUID(s). "
|
||||
"May be repeated to include multiple UUIDs.",
|
||||
),
|
||||
o(
|
||||
"--uuid-from-file",
|
||||
metavar="FILE",
|
||||
default=None,
|
||||
multiple=False,
|
||||
help="Search for photos with UUID(s) loaded from FILE. "
|
||||
"Format is a single UUID per line. Lines preceded with # are ignored.",
|
||||
type=click.Path(exists=True),
|
||||
),
|
||||
o(
|
||||
"--title",
|
||||
metavar="TITLE",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for TITLE in title of photo.",
|
||||
),
|
||||
o("--no-title", is_flag=True, help="Search for photos with no title."),
|
||||
o(
|
||||
"--description",
|
||||
metavar="DESC",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for DESC in description of photo.",
|
||||
),
|
||||
o(
|
||||
"--no-description",
|
||||
is_flag=True,
|
||||
help="Search for photos with no description.",
|
||||
),
|
||||
o(
|
||||
"--place",
|
||||
metavar="PLACE",
|
||||
default=None,
|
||||
multiple=True,
|
||||
help="Search for PLACE in photo's reverse geolocation info",
|
||||
),
|
||||
o(
|
||||
"--no-place",
|
||||
is_flag=True,
|
||||
help="Search for photos with no associated place name info (no reverse geolocation info)",
|
||||
),
|
||||
o(
|
||||
"--location",
|
||||
is_flag=True,
|
||||
help="Search for photos with associated location info (e.g. GPS coordinates)",
|
||||
),
|
||||
o(
|
||||
"--no-location",
|
||||
is_flag=True,
|
||||
help="Search for photos with no associated location info (e.g. no GPS coordinates)",
|
||||
),
|
||||
o(
|
||||
"--label",
|
||||
metavar="LABEL",
|
||||
multiple=True,
|
||||
help="Search for photos with image classification label LABEL (Photos 5+ only). "
|
||||
'If more than one label, treated as "OR", e.g. find photos matching any label',
|
||||
),
|
||||
o(
|
||||
"--uti",
|
||||
metavar="UTI",
|
||||
default=None,
|
||||
multiple=False,
|
||||
help="Search for photos whose uniform type identifier (UTI) matches UTI",
|
||||
),
|
||||
o(
|
||||
"-i",
|
||||
"--ignore-case",
|
||||
is_flag=True,
|
||||
help="Case insensitive search for title, description, place, keyword, person, or album.",
|
||||
),
|
||||
o("--edited", is_flag=True, help="Search for photos that have been edited."),
|
||||
o(
|
||||
"--external-edit",
|
||||
is_flag=True,
|
||||
help="Search for photos edited in external editor.",
|
||||
),
|
||||
o("--favorite", is_flag=True, help="Search for photos marked favorite."),
|
||||
o(
|
||||
"--not-favorite",
|
||||
is_flag=True,
|
||||
help="Search for photos not marked favorite.",
|
||||
),
|
||||
o("--hidden", is_flag=True, help="Search for photos marked hidden."),
|
||||
o("--not-hidden", is_flag=True, help="Search for photos not marked hidden."),
|
||||
o(
|
||||
"--shared",
|
||||
is_flag=True,
|
||||
help="Search for photos in shared iCloud album (Photos 5+ only).",
|
||||
),
|
||||
o(
|
||||
"--not-shared",
|
||||
is_flag=True,
|
||||
help="Search for photos not in shared iCloud album (Photos 5+ only).",
|
||||
),
|
||||
o(
|
||||
"--burst",
|
||||
is_flag=True,
|
||||
help="Search for photos that were taken in a burst.",
|
||||
),
|
||||
o(
|
||||
"--not-burst",
|
||||
is_flag=True,
|
||||
help="Search for photos that are not part of a burst.",
|
||||
),
|
||||
o("--live", is_flag=True, help="Search for Apple live photos"),
|
||||
o(
|
||||
"--not-live",
|
||||
is_flag=True,
|
||||
help="Search for photos that are not Apple live photos.",
|
||||
),
|
||||
o("--portrait", is_flag=True, help="Search for Apple portrait mode photos."),
|
||||
o(
|
||||
"--not-portrait",
|
||||
is_flag=True,
|
||||
help="Search for photos that are not Apple portrait mode photos.",
|
||||
),
|
||||
o("--screenshot", is_flag=True, help="Search for screenshot photos."),
|
||||
o(
|
||||
"--not-screenshot",
|
||||
is_flag=True,
|
||||
help="Search for photos that are not screenshot photos.",
|
||||
),
|
||||
o("--slow-mo", is_flag=True, help="Search for slow motion videos."),
|
||||
o(
|
||||
"--not-slow-mo",
|
||||
is_flag=True,
|
||||
help="Search for photos that are not slow motion videos.",
|
||||
),
|
||||
o("--time-lapse", is_flag=True, help="Search for time lapse videos."),
|
||||
o(
|
||||
"--not-time-lapse",
|
||||
is_flag=True,
|
||||
help="Search for photos that are not time lapse videos.",
|
||||
),
|
||||
o("--hdr", is_flag=True, help="Search for high dynamic range (HDR) photos."),
|
||||
o("--not-hdr", is_flag=True, help="Search for photos that are not HDR photos."),
|
||||
o(
|
||||
"--selfie",
|
||||
is_flag=True,
|
||||
help="Search for selfies (photos taken with front-facing cameras).",
|
||||
),
|
||||
o("--not-selfie", is_flag=True, help="Search for photos that are not selfies."),
|
||||
o("--panorama", is_flag=True, help="Search for panorama photos."),
|
||||
o(
|
||||
"--not-panorama",
|
||||
is_flag=True,
|
||||
help="Search for photos that are not panoramas.",
|
||||
),
|
||||
o(
|
||||
"--has-raw",
|
||||
is_flag=True,
|
||||
help="Search for photos with both a jpeg and raw version",
|
||||
),
|
||||
o(
|
||||
"--only-movies",
|
||||
is_flag=True,
|
||||
help="Search only for movies (default searches both images and movies).",
|
||||
),
|
||||
o(
|
||||
"--only-photos",
|
||||
is_flag=True,
|
||||
help="Search only for photos/images (default searches both images and movies).",
|
||||
),
|
||||
o(
|
||||
"--from-date",
|
||||
help="Search by item start date, e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).",
|
||||
type=DateTimeISO8601(),
|
||||
),
|
||||
o(
|
||||
"--to-date",
|
||||
help="Search by item end date, e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).",
|
||||
type=DateTimeISO8601(),
|
||||
),
|
||||
o(
|
||||
"--from-time",
|
||||
help="Search by item start time of day, e.g. 12:00, or 12:00:00.",
|
||||
type=TimeISO8601(),
|
||||
),
|
||||
o(
|
||||
"--to-time",
|
||||
help="Search by item end time of day, e.g. 12:00 or 12:00:00.",
|
||||
type=TimeISO8601(),
|
||||
),
|
||||
o(
|
||||
"--year",
|
||||
metavar="YEAR",
|
||||
help="Search for items from a specific year, e.g. --year 2022 to find all photos from the year 2022. "
|
||||
"May be repeated to search multiple years.",
|
||||
multiple=True,
|
||||
type=int,
|
||||
),
|
||||
o(
|
||||
"--added-before",
|
||||
metavar="DATE",
|
||||
help="Search for items added to the library before a specific date/time, "
|
||||
"e.g. --added-before e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).",
|
||||
type=DateTimeISO8601(),
|
||||
),
|
||||
o(
|
||||
"--added-after",
|
||||
metavar="DATE",
|
||||
help="Search for items added to the libray after a specific date/time, "
|
||||
"e.g. --added-after e.g. 2000-01-12T12:00:00, 2001-01-12T12:00:00-07:00, or 2000-12-31 (ISO 8601 with/without timezone).",
|
||||
type=DateTimeISO8601(),
|
||||
),
|
||||
o(
|
||||
"--added-in-last",
|
||||
metavar="TIME_DELTA",
|
||||
help="Search for items added to the library in the last TIME_DELTA, "
|
||||
"where TIME_DELTA is a string like "
|
||||
"'12 hrs', '1 day', '1d', '1 week', '2weeks', '1 month', '1 year'. "
|
||||
"for example, `--added-in-last 7d` and `--added-in-last '1 week'` are equivalent. "
|
||||
"months are assumed to be 30 days and years are assumed to be 365 days. "
|
||||
"Common English abbreviations are accepted, e.g. d, day, days or m, min, minutes.",
|
||||
type=TimeOffset(),
|
||||
),
|
||||
o("--has-comment", is_flag=True, help="Search for photos that have comments."),
|
||||
o("--no-comment", is_flag=True, help="Search for photos with no comments."),
|
||||
o("--has-likes", is_flag=True, help="Search for photos that have likes."),
|
||||
o("--no-likes", is_flag=True, help="Search for photos with no likes."),
|
||||
o(
|
||||
"--is-reference",
|
||||
is_flag=True,
|
||||
help="Search for photos that were imported as referenced files (not copied into Photos library).",
|
||||
),
|
||||
o(
|
||||
"--not-reference",
|
||||
is_flag=True,
|
||||
help="Search for photos that are not references, that is, they were copied into the Photos library "
|
||||
"and are managed by Photos.",
|
||||
),
|
||||
o(
|
||||
"--in-album",
|
||||
is_flag=True,
|
||||
help="Search for photos that are in one or more albums.",
|
||||
),
|
||||
o(
|
||||
"--not-in-album",
|
||||
is_flag=True,
|
||||
help="Search for photos that are not in any albums.",
|
||||
),
|
||||
o(
|
||||
"--duplicate",
|
||||
is_flag=True,
|
||||
help="Search for photos with possible duplicates. osxphotos will compare signatures of photos, "
|
||||
"evaluating date created, size, height, width, and edited status to find *possible* duplicates. "
|
||||
"This does not compare images byte-for-byte nor compare hashes but should find photos imported multiple "
|
||||
"times or duplicated within Photos.",
|
||||
),
|
||||
o(
|
||||
"--min-size",
|
||||
metavar="SIZE",
|
||||
type=BitMathSize(),
|
||||
help="Search for photos with size >= SIZE bytes. "
|
||||
"The size evaluated is the photo's original size (when imported to Photos). "
|
||||
"Size may be specified as integer bytes or using SI or NIST units. "
|
||||
"For example, the following are all valid and equivalent sizes: '1048576' '1.048576MB', '1 MiB'.",
|
||||
),
|
||||
o(
|
||||
"--max-size",
|
||||
metavar="SIZE",
|
||||
type=BitMathSize(),
|
||||
help="Search for photos with size <= SIZE bytes. "
|
||||
"The size evaluated is the photo's original size (when imported to Photos). "
|
||||
"Size may be specified as integer bytes or using SI or NIST units. "
|
||||
"For example, the following are all valid and equivalent sizes: '1048576' '1.048576MB', '1 MiB'.",
|
||||
),
|
||||
o("--missing", is_flag=True, help="Search for photos missing from disk."),
|
||||
o(
|
||||
"--not-missing",
|
||||
is_flag=True,
|
||||
help="Search for photos present on disk (e.g. not missing).",
|
||||
),
|
||||
o(
|
||||
"--cloudasset",
|
||||
is_flag=True,
|
||||
help="Search for photos that are part of an iCloud library",
|
||||
),
|
||||
o(
|
||||
"--not-cloudasset",
|
||||
is_flag=True,
|
||||
help="Search for photos that are not part of an iCloud library",
|
||||
),
|
||||
o(
|
||||
"--incloud",
|
||||
is_flag=True,
|
||||
help="Search for photos that are in iCloud (have been synched)",
|
||||
),
|
||||
o(
|
||||
"--not-incloud",
|
||||
is_flag=True,
|
||||
help="Search for photos that are not in iCloud (have not been synched)",
|
||||
),
|
||||
o(
|
||||
"--regex",
|
||||
metavar="REGEX TEMPLATE",
|
||||
nargs=2,
|
||||
multiple=True,
|
||||
help="Search for photos where TEMPLATE matches regular expression REGEX. "
|
||||
"For example, to find photos in an album that begins with 'Beach': '--regex \"^Beach\" \"{album}\"'. "
|
||||
"You may specify more than one regular expression match by repeating '--regex' with different arguments.",
|
||||
),
|
||||
o(
|
||||
"--selected",
|
||||
is_flag=True,
|
||||
help="Filter for photos that are currently selected in Photos.",
|
||||
),
|
||||
o(
|
||||
"--exif",
|
||||
metavar="EXIF_TAG VALUE",
|
||||
nargs=2,
|
||||
multiple=True,
|
||||
help="Search for photos where EXIF_TAG exists in photo's EXIF data and contains VALUE. "
|
||||
"For example, to find photos created by Adobe Photoshop: `--exif Software 'Adobe Photoshop' `"
|
||||
"or to find all photos shot on a Canon camera: `--exif Make Canon`. "
|
||||
"EXIF_TAG can be any valid exiftool tag, with or without group name, e.g. `EXIF:Make` or `Make`. "
|
||||
"To use --exif, exiftool must be installed and in the path.",
|
||||
),
|
||||
o(
|
||||
"--query-eval",
|
||||
metavar="CRITERIA",
|
||||
multiple=True,
|
||||
help="Evaluate CRITERIA to filter photos. "
|
||||
"CRITERIA will be evaluated in context of the following python list comprehension: "
|
||||
"`photos = [photo for photo in photos if CRITERIA]` "
|
||||
"where photo represents a PhotoInfo object. "
|
||||
"For example: `--query-eval photo.favorite` returns all photos that have been "
|
||||
"favorited and is equivalent to --favorite. "
|
||||
"You may specify more than one CRITERIA by using --query-eval multiple times. "
|
||||
"CRITERIA must be a valid python expression. "
|
||||
"See https://rhettbull.github.io/osxphotos/ for additional documentation on the PhotoInfo class.",
|
||||
),
|
||||
o(
|
||||
"--query-function",
|
||||
metavar="filename.py::function",
|
||||
multiple=True,
|
||||
type=FunctionCall(),
|
||||
help="Run function to filter photos. Use this in format: --query-function filename.py::function where filename.py is a python "
|
||||
+ "file you've created and function is the name of the function in the python file you want to call. "
|
||||
+ "Your function will be passed a list of PhotoInfo objects and is expected to return a filtered list of PhotoInfo objects. "
|
||||
+ "You may use more than one function by repeating the --query-function option with a different value. "
|
||||
+ "Your query function will be called after all other query options have been evaluated. "
|
||||
+ "See https://github.com/RhetTbull/osxphotos/blob/master/examples/query_function.py for example of how to use this option.",
|
||||
),
|
||||
]
|
||||
for o in options[::-1]:
|
||||
f = o(f)
|
||||
return f
|
||||
|
||||
|
||||
def DEBUG_OPTIONS(f):
|
||||
o = click.option
|
||||
options = [
|
||||
o(
|
||||
"--debug",
|
||||
is_flag=True,
|
||||
help="Enable debug output.",
|
||||
hidden=OSXPHOTOS_HIDDEN,
|
||||
),
|
||||
o(
|
||||
"--watch",
|
||||
metavar="MODULE::NAME",
|
||||
multiple=True,
|
||||
help="Watch function or method calls. The function to watch must be in the form "
|
||||
"MODULE::NAME where MODULE is the module path and NAME is the function or method name "
|
||||
"contained in the module. For example, to watch all calls to FileUtil.copy() which is in "
|
||||
"osxphotos.fileutil, use: "
|
||||
"'--watch osxphotos.fileutil::FileUtil.copy'. More than one --watch option can be specified.",
|
||||
hidden=OSXPHOTOS_HIDDEN,
|
||||
),
|
||||
o(
|
||||
"--breakpoint",
|
||||
metavar="MODULE::NAME",
|
||||
multiple=True,
|
||||
help="Add breakpoint to function calls. The function to watch must be in the form "
|
||||
"MODULE::NAME where MODULE is the module path and NAME is the function or method name "
|
||||
"contained in the module. For example, to set a breakpoint for calls to "
|
||||
"FileUtil.copy() which is in osxphotos.fileutil, use: "
|
||||
"'--breakpoint osxphotos.fileutil::FileUtil.copy'. More than one --breakpoint option can be specified.",
|
||||
hidden=OSXPHOTOS_HIDDEN,
|
||||
),
|
||||
]
|
||||
for o in options[::-1]:
|
||||
f = o(f)
|
||||
return f
|
||||
|
||||
|
||||
THEME_OPTION = click.option(
|
||||
"--theme",
|
||||
metavar="THEME",
|
||||
type=click.Choice(["dark", "light", "mono", "plain"], case_sensitive=False),
|
||||
help="Specify the color theme to use for --verbose output. "
|
||||
"Valid themes are 'dark', 'light', 'mono', and 'plain'. "
|
||||
"Defaults to 'dark' or 'light' depending on system dark mode setting.",
|
||||
)
|
||||
|
||||
|
||||
def load_uuid_from_file(filename):
|
||||
"""Load UUIDs from file. Does not validate UUIDs.
|
||||
Format is 1 UUID per line, any line beginning with # is ignored.
|
||||
Whitespace is stripped.
|
||||
|
||||
Arguments:
|
||||
filename: file name of the file containing UUIDs
|
||||
|
||||
Returns:
|
||||
list of UUIDs or empty list of no UUIDs in file
|
||||
|
||||
Raises:
|
||||
FileNotFoundError if file does not exist
|
||||
"""
|
||||
|
||||
if not pathlib.Path(filename).is_file():
|
||||
raise FileNotFoundError(f"Could not find file {filename}")
|
||||
|
||||
uuid = []
|
||||
with open(filename, "r") as uuid_file:
|
||||
for line in uuid_file:
|
||||
line = line.strip()
|
||||
if len(line) and line[0] != "#":
|
||||
uuid.append(line)
|
||||
return uuid
|
||||
|
||||
|
||||
def get_config_dir() -> pathlib.Path:
|
||||
"""Get the directory where config files are stored; create it if necessary."""
|
||||
config_dir = xdg_config_home() / APP_NAME
|
||||
@@ -671,101 +111,11 @@ def check_version():
|
||||
)
|
||||
|
||||
|
||||
def query_options_from_kwargs(**kwargs) -> QueryOptions:
|
||||
"""Validate query options and create a QueryOptions instance"""
|
||||
# sanity check input args
|
||||
nonexclusive = [
|
||||
"added_after",
|
||||
"added_before",
|
||||
"added_in_last",
|
||||
"album",
|
||||
"duplicate",
|
||||
"edited",
|
||||
"exif",
|
||||
"external_edit",
|
||||
"folder",
|
||||
"from_date",
|
||||
"from_time",
|
||||
"has_raw",
|
||||
"keyword",
|
||||
"label",
|
||||
"max_size",
|
||||
"min_size",
|
||||
"name",
|
||||
"person",
|
||||
"query_eval",
|
||||
"query_function",
|
||||
"regex",
|
||||
"selected",
|
||||
"to_date",
|
||||
"to_time",
|
||||
"uti",
|
||||
"uuid_from_file",
|
||||
"uuid",
|
||||
"year",
|
||||
]
|
||||
exclusive = [
|
||||
("burst", "not_burst"),
|
||||
("cloudasset", "not_cloudasset"),
|
||||
("favorite", "not_favorite"),
|
||||
("has_comment", "no_comment"),
|
||||
("has_likes", "no_likes"),
|
||||
("hdr", "not_hdr"),
|
||||
("hidden", "not_hidden"),
|
||||
("in_album", "not_in_album"),
|
||||
("incloud", "not_incloud"),
|
||||
("live", "not_live"),
|
||||
("location", "no_location"),
|
||||
("keyword", "no_keyword"),
|
||||
("missing", "not_missing"),
|
||||
("only_photos", "only_movies"),
|
||||
("panorama", "not_panorama"),
|
||||
("portrait", "not_portrait"),
|
||||
("screenshot", "not_screenshot"),
|
||||
("selfie", "not_selfie"),
|
||||
("shared", "not_shared"),
|
||||
("slow_mo", "not_slow_mo"),
|
||||
("time_lapse", "not_time_lapse"),
|
||||
("is_reference", "not_reference"),
|
||||
]
|
||||
# print help if no non-exclusive term or a double exclusive term is given
|
||||
# TODO: add option to validate requiring at least one query arg
|
||||
if any(all([kwargs[b], kwargs[n]]) for b, n in exclusive) or any(
|
||||
[
|
||||
all([any(kwargs["title"]), kwargs["no_title"]]),
|
||||
all([any(kwargs["description"]), kwargs["no_description"]]),
|
||||
all([any(kwargs["place"]), kwargs["no_place"]]),
|
||||
all([any(kwargs["keyword"]), kwargs["no_keyword"]]),
|
||||
]
|
||||
):
|
||||
raise IncompatibleQueryOptions
|
||||
|
||||
# can also be used with --deleted/--not-deleted which are not part of
|
||||
# standard query options
|
||||
try:
|
||||
if kwargs["deleted"] and kwargs["not_deleted"]:
|
||||
raise IncompatibleQueryOptions
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# actually have something to query
|
||||
include_photos = True
|
||||
include_movies = True # default searches for everything
|
||||
if kwargs["only_movies"]:
|
||||
include_photos = False
|
||||
if kwargs["only_photos"]:
|
||||
include_movies = False
|
||||
|
||||
# load UUIDs if necessary and append to any uuids passed with --uuid
|
||||
uuid = None
|
||||
if kwargs["uuid_from_file"]:
|
||||
uuid_list = list(kwargs["uuid"]) # Click option is a tuple
|
||||
uuid_list.extend(load_uuid_from_file(kwargs["uuid_from_file"]))
|
||||
uuid = tuple(uuid_list)
|
||||
|
||||
query_fields = [field.name for field in dataclasses.fields(QueryOptions)]
|
||||
query_dict = {field: kwargs.get(field) for field in query_fields}
|
||||
query_dict["photos"] = include_photos
|
||||
query_dict["movies"] = include_movies
|
||||
query_dict["uuid"] = uuid
|
||||
return QueryOptions(**query_dict)
|
||||
def print_version(ctx, param, value):
|
||||
"""Print version, this is a callback for the --version option"""
|
||||
if not value:
|
||||
return
|
||||
click.echo(f"osxphotos, version {__version__}")
|
||||
click.echo(f"Python {sys.version}")
|
||||
click.echo(f"macOS {'.'.join(get_macos_version())}, {platform.machine()}")
|
||||
ctx.exit()
|
||||
|
||||
@@ -1,19 +1,30 @@
|
||||
"""Detect dark mode on MacOS >= 10.14"""
|
||||
"""Detect dark mode on MacOS >= 10.14 or fake it elsewhere"""
|
||||
|
||||
import objc
|
||||
import Foundation
|
||||
from osxphotos.platform import is_macos
|
||||
|
||||
if is_macos:
|
||||
import Foundation
|
||||
import objc
|
||||
|
||||
def theme():
|
||||
with objc.autorelease_pool():
|
||||
user_defaults = Foundation.NSUserDefaults.standardUserDefaults()
|
||||
system_theme = user_defaults.stringForKey_("AppleInterfaceStyle")
|
||||
return "dark" if system_theme == "Dark" else "light"
|
||||
def theme():
|
||||
with objc.autorelease_pool():
|
||||
user_defaults = Foundation.NSUserDefaults.standardUserDefaults()
|
||||
system_theme = user_defaults.stringForKey_("AppleInterfaceStyle")
|
||||
return "dark" if system_theme == "Dark" else "light"
|
||||
|
||||
def is_dark_mode():
|
||||
return theme() == "dark"
|
||||
|
||||
def is_dark_mode():
|
||||
return theme() == "dark"
|
||||
def is_light_mode():
|
||||
return theme() == "light"
|
||||
|
||||
else:
|
||||
|
||||
def is_light_mode():
|
||||
return theme() == "light"
|
||||
def theme():
|
||||
return "light"
|
||||
|
||||
def is_dark_mode():
|
||||
return theme() == "dark"
|
||||
|
||||
def is_light_mode():
|
||||
return theme() == "light"
|
||||
|
||||
@@ -8,8 +8,17 @@ from rich import print
|
||||
|
||||
import osxphotos
|
||||
from osxphotos._constants import _PHOTOS_4_VERSION, _UNKNOWN_PLACE
|
||||
from osxphotos.queryoptions import query_options_from_kwargs
|
||||
|
||||
from .common import DB_ARGUMENT, DB_OPTION, JSON_OPTION, OSXPHOTOS_HIDDEN, get_photos_db
|
||||
from .cli_params import (
|
||||
DB_ARGUMENT,
|
||||
DB_OPTION,
|
||||
JSON_OPTION,
|
||||
QUERY_OPTIONS,
|
||||
TIMESTAMP_OPTION,
|
||||
VERBOSE_OPTION,
|
||||
)
|
||||
from .common import OSXPHOTOS_HIDDEN, get_photos_db
|
||||
from .list import _list_libraries
|
||||
from .verbose import verbose_print
|
||||
|
||||
@@ -24,30 +33,35 @@ from .verbose import verbose_print
|
||||
+ "can also use albums, persons, keywords, photos to dump related attributes.",
|
||||
multiple=True,
|
||||
)
|
||||
@click.option(
|
||||
"--uuid",
|
||||
metavar="UUID",
|
||||
help="Use with '--dump photos' to dump only certain UUIDs. "
|
||||
"May be repeated to include multiple UUIDs.",
|
||||
multiple=True,
|
||||
)
|
||||
@click.option("--verbose", "-V", "verbose", is_flag=True, help="Print verbose output.")
|
||||
@VERBOSE_OPTION
|
||||
@TIMESTAMP_OPTION
|
||||
@QUERY_OPTIONS
|
||||
@click.pass_obj
|
||||
@click.pass_context
|
||||
def debug_dump(ctx, cli_obj, db, photos_library, dump, uuid, verbose):
|
||||
"""Print out debug info"""
|
||||
def debug_dump(
|
||||
ctx, cli_obj, db, photos_library, dump, verbose_flag, timestamp, **kwargs
|
||||
):
|
||||
"""Print out debug info.
|
||||
|
||||
verbose_ = verbose_print(verbose, rich=True)
|
||||
db = get_photos_db(*photos_library, db, cli_obj.db)
|
||||
When run with --dump photos, any of the query options can be used to limit the
|
||||
photos printed. For example, to print info on currently selected photos:
|
||||
|
||||
osxphotos debug-dump --dump photos --selected
|
||||
"""
|
||||
|
||||
verbose = verbose_print(verbose_flag, timestamp)
|
||||
db = get_photos_db(*photos_library, db, cli_obj.db if cli_obj else None)
|
||||
if db is None:
|
||||
click.echo(ctx.obj.group.commands["debug-dump"].get_help(ctx), err=True)
|
||||
click.echo("\n\nLocated the following Photos library databases: ", err=True)
|
||||
_list_libraries()
|
||||
return
|
||||
|
||||
query_options = query_options_from_kwargs(**kwargs)
|
||||
|
||||
start_t = time.perf_counter()
|
||||
print(f"Opening database: {db}")
|
||||
photosdb = osxphotos.PhotosDB(dbfile=db, verbose=verbose_)
|
||||
photosdb = osxphotos.PhotosDB(dbfile=db, verbose=verbose)
|
||||
stop_t = time.perf_counter()
|
||||
print(f"Done; took {(stop_t-start_t):.2f} seconds")
|
||||
|
||||
@@ -78,16 +92,26 @@ def debug_dump(ctx, cli_obj, db, photos_library, dump, uuid, verbose):
|
||||
print("_dbpersons_fullname:")
|
||||
pprint.pprint(photosdb._dbpersons_fullname)
|
||||
elif attr == "photos":
|
||||
if uuid:
|
||||
for uuid_ in uuid:
|
||||
print(f"_dbphotos['{uuid_}']:")
|
||||
try:
|
||||
pprint.pprint(photosdb._dbphotos[uuid_])
|
||||
except KeyError:
|
||||
print(f"Did not find uuid {uuid_} in _dbphotos")
|
||||
else:
|
||||
print("_dbphotos:")
|
||||
pprint.pprint(photosdb._dbphotos)
|
||||
photos = photosdb.query(options=query_options)
|
||||
for p in photos:
|
||||
# print info on each photo
|
||||
# catch any errors and continue (because if we're using debug-dump, it might be because of an error)
|
||||
print(f"photo: {p.uuid}")
|
||||
print(f"_dbphotos['{p.uuid}']:")
|
||||
try:
|
||||
print(photosdb._dbphotos[p.uuid])
|
||||
except KeyError:
|
||||
print(f"Did not find uuid {p.uuid} in _dbphotos")
|
||||
print("PhotoInfo:")
|
||||
try:
|
||||
print(p.asdict(shallow=False))
|
||||
except Exception as e:
|
||||
print(f"Error dumping PhotoInfo.asdict(): {e}")
|
||||
print("ZASSET")
|
||||
print(p.tables().ZASSET.rows_dict())
|
||||
print("ZADDITIONALASSETATTRIBUTES")
|
||||
print(p.tables().ZADDITIONALASSETATTRIBUTES.rows_dict())
|
||||
print("-" * 40)
|
||||
else:
|
||||
try:
|
||||
val = getattr(photosdb, attr)
|
||||
|
||||
@@ -13,10 +13,10 @@ from osxphotos._version import __version__
|
||||
from .common import get_config_dir, get_data_dir
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.command(name="docs")
|
||||
@click.pass_obj
|
||||
@click.pass_context
|
||||
def docs(ctx, cli_obj):
|
||||
def docs_command(ctx, cli_obj):
|
||||
"""Open osxphotos documentation in your browser."""
|
||||
|
||||
# first check if docs installed in old location in confir dir and if so, delete them
|
||||
|
||||
@@ -11,15 +11,15 @@ from osxphotos.cli.click_rich_echo import (
|
||||
from osxphotos.phototemplate import RenderOptions
|
||||
from osxphotos.queryoptions import QueryOptions
|
||||
|
||||
from .color_themes import get_default_theme
|
||||
from .common import (
|
||||
from .cli_params import (
|
||||
DB_ARGUMENT,
|
||||
DB_OPTION,
|
||||
DELETED_OPTIONS,
|
||||
FIELD_OPTION,
|
||||
JSON_OPTION,
|
||||
get_photos_db,
|
||||
)
|
||||
from .color_themes import get_default_theme
|
||||
from .common import get_photos_db
|
||||
from .list import _list_libraries
|
||||
from .print_photo_info import print_photo_fields, print_photo_info
|
||||
from .verbose import get_verbose_console
|
||||
@@ -56,7 +56,11 @@ def dump(
|
||||
photos_library,
|
||||
print_template,
|
||||
):
|
||||
"""Print list of all photos & associated info from the Photos library."""
|
||||
"""Print list of all photos & associated info from the Photos library.
|
||||
|
||||
NOTE: dump is DEPRECATED and will be removed in a future release.
|
||||
Use `osxphotos query` instead.
|
||||
"""
|
||||
|
||||
# below needed for to make CliRunner work for testing
|
||||
cli_db = cli_obj.db if cli_obj is not None else None
|
||||
|
||||
@@ -17,15 +17,9 @@ from osxphotos.fileutil import FileUtil, FileUtilNoOp
|
||||
from osxphotos.photoexporter import ExportOptions, ExportResults, PhotoExporter
|
||||
from osxphotos.utils import pluralize
|
||||
|
||||
from .click_rich_echo import (
|
||||
rich_click_echo,
|
||||
rich_echo_error,
|
||||
set_rich_console,
|
||||
set_rich_theme,
|
||||
set_rich_timestamp,
|
||||
)
|
||||
from .color_themes import get_theme
|
||||
from .common import DB_OPTION, THEME_OPTION, get_photos_db
|
||||
from .cli_params import DB_OPTION, THEME_OPTION, TIMESTAMP_OPTION, VERBOSE_OPTION
|
||||
from .click_rich_echo import rich_click_echo, rich_echo_error
|
||||
from .common import get_photos_db
|
||||
from .export import export, render_and_validate_report
|
||||
from .param_types import ExportDBType, TemplateString
|
||||
from .report_writer import ReportWriterNoOp, export_report_writer_factory
|
||||
@@ -166,8 +160,8 @@ from .verbose import get_verbose_console, verbose_print
|
||||
help="If used with --report, add data to existing report file instead of overwriting it. "
|
||||
"See also --report.",
|
||||
)
|
||||
@click.option("--verbose", "-V", is_flag=True, help="Print verbose output.")
|
||||
@click.option("--timestamp", is_flag=True, help="Add time stamp to verbose output")
|
||||
@VERBOSE_OPTION
|
||||
@TIMESTAMP_OPTION
|
||||
@click.option(
|
||||
"--dry-run",
|
||||
is_flag=True,
|
||||
@@ -203,7 +197,7 @@ def exiftool(
|
||||
save_config,
|
||||
theme,
|
||||
timestamp,
|
||||
verbose,
|
||||
verbose_flag,
|
||||
):
|
||||
"""Run exiftool on previously exported files to update metadata.
|
||||
|
||||
@@ -235,6 +229,7 @@ def exiftool(
|
||||
|
||||
# need to ensure --exiftool is true in the config options
|
||||
locals_["exiftool"] = True
|
||||
locals_["verbose"] = verbose_flag
|
||||
config = ConfigOptions(
|
||||
"export",
|
||||
locals_,
|
||||
@@ -249,14 +244,7 @@ def exiftool(
|
||||
"save_config",
|
||||
],
|
||||
)
|
||||
color_theme = get_theme(theme)
|
||||
verbose_ = verbose_print(
|
||||
verbose, timestamp, rich=True, theme=color_theme, highlight=False
|
||||
)
|
||||
# set console for rich_echo to be same as for verbose_
|
||||
set_rich_console(get_verbose_console())
|
||||
set_rich_theme(color_theme)
|
||||
set_rich_timestamp(timestamp)
|
||||
verbose = verbose_print(verbose_flag, timestamp, theme=theme)
|
||||
|
||||
# load config options from either file or export database
|
||||
# values already set in config will take precedence over any values
|
||||
@@ -269,26 +257,16 @@ def exiftool(
|
||||
f"[error]Error parsing {load_config} config file: {e.message}", err=True
|
||||
)
|
||||
sys.exit(1)
|
||||
verbose_(f"Loaded options from file [filepath]{load_config}")
|
||||
verbose(f"Loaded options from file [filepath]{load_config}")
|
||||
elif db_config:
|
||||
config = export_db_get_config(exportdb, config)
|
||||
verbose_("Loaded options from export database")
|
||||
verbose("Loaded options from export database")
|
||||
|
||||
# from here on out, use config.param_name instead of using the params passed into the function
|
||||
# as the values may have been updated from config file or database
|
||||
if load_config or db_config:
|
||||
# config file might have changed verbose
|
||||
color_theme = get_theme(config.theme)
|
||||
verbose_ = verbose_print(
|
||||
config.verbose,
|
||||
config.timestamp,
|
||||
rich=True,
|
||||
theme=color_theme,
|
||||
highlight=False,
|
||||
)
|
||||
# set console for rich_echo to be same as for verbose_
|
||||
set_rich_console(get_verbose_console())
|
||||
set_rich_timestamp(config.timestamp)
|
||||
verbose = verbose_print(config.verbose, config.timestamp, theme=theme)
|
||||
|
||||
# validate options
|
||||
if append and not report:
|
||||
@@ -298,14 +276,14 @@ def exiftool(
|
||||
config.db = get_photos_db(config.db)
|
||||
|
||||
if save_config:
|
||||
verbose_(f"Saving options to config file '[filepath]{save_config}'")
|
||||
verbose(f"Saving options to config file '[filepath]{save_config}'")
|
||||
config.write_to_file(save_config)
|
||||
|
||||
process_files(exportdb, export_dir, verbose=verbose_, options=config)
|
||||
process_files(exportdb, export_dir, verbose=verbose, options=config)
|
||||
|
||||
|
||||
def process_files(
|
||||
exportdb: str, export_dir: str, verbose: Callable, options: ConfigOptions
|
||||
exportdb: str, export_dir: str, verbose: Callable[..., None], options: ConfigOptions
|
||||
):
|
||||
"""Process files in the export database.
|
||||
|
||||
@@ -362,6 +340,12 @@ def process_files(
|
||||
hardlink_ok = True
|
||||
verbose(f"Processing file [filepath]{file}[/] ([num]{count}/{total}[/num])")
|
||||
photo = photosdb.get_photo(uuid)
|
||||
if not photo:
|
||||
verbose(
|
||||
f"Could not find photo for [filepath]{file}[/] ([uuid]{uuid}[/])"
|
||||
)
|
||||
report_writer.write(ExportResults(missing=[file]))
|
||||
continue
|
||||
export_options = ExportOptions(
|
||||
description_template=options.description_template,
|
||||
dry_run=options.dry_run,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user