Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eee8ff85ac | ||
|
|
d3a6fed119 | ||
|
|
1b8a254bd8 | ||
|
|
f1cee7959d | ||
|
|
a9843ac60e | ||
|
|
51b1abccf8 | ||
|
|
d7cf66b11f | ||
|
|
bc0123ccdb | ||
|
|
d6ca010fa5 | ||
|
|
bb1f93a964 | ||
|
|
8be71243d5 | ||
|
|
e53d223f2d | ||
|
|
009e17b75c | ||
|
|
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 |
@ -184,7 +184,8 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/42419?v=4",
|
||||
"profile": "https://neilpa.me",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 0.60.7
|
||||
current_version = 0.62.1
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
|
||||
serialize = {major}.{minor}.{patch}
|
||||
|
||||
|
||||
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
|
||||
|
||||
111
API_README.md
111
API_README.md
@ -57,11 +57,12 @@ osxphotos provides several useful helper functions to make it easy to build simp
|
||||
Here's a simple example showing how to use the `query_command` decorator to implement a simple command line tool. The `query_command` decorator turns your function into a full-fledged [Click](https://palletsprojects.com/p/click/) command line app that can be run via `osxphotos run example.py` or `python example.py` if you have pip installed osxphotos. Your command will include all the query options available in `osxphotos query` as command line options as well as `--verbose` and other convenient options.
|
||||
|
||||
<!--[[[cog
|
||||
cog.out("```python\n")
|
||||
cog.out("\n```python\n")
|
||||
with open("examples/cli_example_1.py", "r") as f:
|
||||
cog.out(f.read())
|
||||
cog.out("```\n")
|
||||
]]]-->
|
||||
|
||||
```python
|
||||
"""Sample query command for osxphotos
|
||||
|
||||
@ -136,11 +137,12 @@ if __name__ == "__main__":
|
||||
Here is a more advanced example that shows how to implement a script with a "dry run" and "resume" capability that preserves state between runs. Using the built-in helpers allows you to implement complex behavior in just a few lines of code.
|
||||
|
||||
<!--[[[cog
|
||||
cog.out("```python\n")
|
||||
cog.out("\n```python\n")
|
||||
with open("examples/cli_example_2.py", "r") as f:
|
||||
cog.out(f.read())
|
||||
cog.out("```\n")
|
||||
]]]-->
|
||||
|
||||
```python
|
||||
"""Sample query command for osxphotos
|
||||
|
||||
@ -308,11 +310,12 @@ if __name__ == "__main__":
|
||||
In addition to the `query_command` decorator, you can also use the `selection_command` decorator to implement a command that operates on the current selection in Photos.
|
||||
|
||||
<!--[[[cog
|
||||
cog.out("```python\n")
|
||||
cog.out("\n```python\n")
|
||||
with open("examples/cli_example_3.py", "r") as f:
|
||||
cog.out(f.read())
|
||||
cog.out("```\n")
|
||||
]]]-->
|
||||
|
||||
```python
|
||||
"""Sample query command for osxphotos
|
||||
|
||||
@ -442,7 +445,7 @@ if __name__ == "__main__":
|
||||
|
||||
## Package Interface
|
||||
|
||||
### PhotosDB
|
||||
### <a name="photosdb">PhotosDB</a>
|
||||
|
||||
#### Read a Photos library database
|
||||
|
||||
@ -633,11 +636,11 @@ For example, in my library, Photos says I have 19,386 photos and 474 movies. Ho
|
||||
|
||||
Returns a single PhotoInfo instance for photo with UUID matching `uuid` or None if no photo is found matching `uuid`. If you know the UUID of a photo, `get_photo()` is much faster than `photos`. See also [photos()](#photos).
|
||||
|
||||
#### <A name="photosdbquery">`query(options: QueryOptions) -> List[PhotoInfo]:`</a>
|
||||
#### <A name="photosdb_query">`query(options: QueryOptions) -> List[PhotoInfo]:`</a>
|
||||
|
||||
Returns a list of [PhotoInfo](#photoinfo) objects matching the query options. This is preferred method of querying the photos database. See [QueryOptions](#queryoptions) for details on the options available.
|
||||
|
||||
#### `keywords`
|
||||
#### <a name="photosdb_keywords">`keywords`</a>
|
||||
|
||||
```python
|
||||
# assumes photosdb is a PhotosDB object (see above)
|
||||
@ -646,16 +649,16 @@ keywords = photosdb.keywords
|
||||
|
||||
Returns a list of the keywords found in the Photos library
|
||||
|
||||
#### <a name="photosdbalbuminfo">`album_info`</a>
|
||||
#### <a name="photosdb_albuminfo">`album_info`</a>
|
||||
|
||||
```python
|
||||
# assumes photosdb is a PhotosDB object (see above)
|
||||
albums = photosdb.album_info
|
||||
```
|
||||
|
||||
Returns a list of [AlbumInfo](#albuminfo) objects representing albums in the database or empty list if there are no albums. See also [albums](#albums) and [burst_album_info](#burst_album_info).
|
||||
Returns a list of [AlbumInfo](#albuminfo) objects representing albums in the database or empty list if there are no albums. See also [albums](#photosdb_albums) and [burst_album_info](#burst_album_info).
|
||||
|
||||
#### `albums`
|
||||
#### <a name="photosdb_albums">`albums`</a>
|
||||
|
||||
```python
|
||||
# assumes photosdb is a PhotosDB object (see above)
|
||||
@ -666,7 +669,7 @@ Returns a list of the album names found in the Photos library. See also [burst_a
|
||||
|
||||
**Note**: In Photos 5.0 (MacOS 10.15/Catalina), It is possible to have more than one album with the same name in Photos. Albums with duplicate names are treated as a single album and the photos in each are combined. For example, if you have two albums named "Wedding" and each has 2 photos, osxphotos will treat this as a single album named "Wedding" with 4 photos in it.
|
||||
|
||||
See also [album_info](#album_info.)
|
||||
See also [album_info](#photosdb_album_info.)
|
||||
|
||||
#### `albums_shared`
|
||||
|
||||
@ -674,30 +677,30 @@ Returns list of shared album names found in photos database (e.g. albums shared
|
||||
|
||||
**Note**: *Only valid for Photos 5 / MacOS 10.15*; on Photos <= 4, prints warning and returns empty list.
|
||||
|
||||
#### `import_info`
|
||||
#### <a name = "photosdb_import_info">`import_info`</a>
|
||||
|
||||
Returns a list of [ImportInfo](#importinfo) objects representing the import sessions for the database.
|
||||
|
||||
#### `project_info`
|
||||
#### <a name="photosdb_project_info">`project_info`</a>
|
||||
|
||||
Returns a list of [ProjectInfo](#projectinfo) objects representing the projects/creations (cards, calendars, etc.) in the database.
|
||||
|
||||
#### `moment_info`
|
||||
#### <a name="photosdb_moment_info">`moment_info`</a>
|
||||
|
||||
Returns the [MomentInfo](#momentinfo) object for the photo or `None` if the photo does not have an associated moment.
|
||||
|
||||
#### `folder_info`
|
||||
#### <a name="photosdb_folder_info">`folder_info`</a>
|
||||
|
||||
```python
|
||||
# assumes photosdb is a PhotosDB object (see above)
|
||||
folders = photosdb.folder_info
|
||||
```
|
||||
|
||||
Returns a list of [FolderInfo](#folderinfo) objects representing top level folders in the database or empty list if there are no folders. See also [folders](#folders).
|
||||
Returns a list of [FolderInfo](#folderinfo) objects representing top level folders in the database or empty list if there are no folders. See also [folders](#photosdb_folders).
|
||||
|
||||
**Note**: Currently folder_info is only implemented for Photos 5 (Catalina); will return empty list and output warning if called on earlier database versions.
|
||||
|
||||
#### `folders`
|
||||
#### <a name="photosdb_folders">`folders`</a>
|
||||
|
||||
```python
|
||||
# assumes photosdb is a PhotosDB object (see above)
|
||||
@ -708,16 +711,16 @@ Returns a list names of top level folder names in the database.
|
||||
|
||||
**Note**: Currently folders is only implemented for Photos 5 (Catalina); will return empty list and output warning if called on earlier database versions.
|
||||
|
||||
#### `persons`
|
||||
#### <a name="photosdb_persons">`persons`</a>
|
||||
|
||||
```python
|
||||
# assumes photosdb is a PhotosDB object (see above)
|
||||
persons = photosdb.persons
|
||||
```
|
||||
|
||||
Returns a list of the person names (faces) found in the Photos library. **Note**: It is of course possible to have more than one person with the same name, e.g. "Maria Smith", in the database. `persons` assumes these are the same person and will list only one person named "Maria Smith". If you need more information about persons in the database, see [person_info](#dbpersoninfo).
|
||||
Returns a list of the person names (faces) found in the Photos library. **Note**: It is of course possible to have more than one person with the same name, e.g. "Maria Smith", in the database. `persons` assumes these are the same person and will list only one person named "Maria Smith". If you need more information about persons in the database, see [person_info](#photosdb_personinfo).
|
||||
|
||||
#### <a name="dbpersoninfo">`person_info`</a>
|
||||
#### <a name="photosdb_person_info">`person_info`</a>
|
||||
|
||||
```python
|
||||
# assumes photosdb is a PhotosDB object (see above)
|
||||
@ -766,17 +769,17 @@ Returns a dictionary of shared albums (e.g. shared via iCloud photo sharing) fou
|
||||
|
||||
**Note**: *Photos 5 / MacOS 10.15 only*. On earlier versions of Photos, prints warning and returns empty dictionary.
|
||||
|
||||
#### `labels`
|
||||
#### <a name="photosdb_labels">`labels`</a>
|
||||
|
||||
Returns image categorization labels associated with photos in the library as list of str.
|
||||
|
||||
**Note**: Only valid on Photos 5; on earlier versions, returns empty list. In Photos 5, Photos runs machine learning image categorization against photos in the library and automatically assigns labels to photos such as "People", "Dog", "Water", etc. A photo may have zero or more labels associated with it. See also [labels_normalized](#labels_normalized).
|
||||
**Note**: Only valid on Photos 5; on earlier versions, returns empty list. In Photos 5, Photos runs machine learning image categorization against photos in the library and automatically assigns labels to photos such as "People", "Dog", "Water", etc. A photo may have zero or more labels associated with it. See also [labels_normalized](#photosdb_labels_normalized).
|
||||
|
||||
#### `labels_normalized`
|
||||
#### <a name="photosdb_labels_normalized">`labels_normalized`</a>
|
||||
|
||||
Returns image categorization labels associated with photos in the library as list of str. Labels are normalized (e.g. converted to lower case). Use of normalized strings makes it easier to search if you don't how Apple capitalizes a label.
|
||||
|
||||
**Note**: Only valid on Photos 5; on earlier versions, returns empty list. In Photos 5, Photos runs machine learning image categorization against photos in the library and automatically assigns labels to photos such as "People", "Dog", "Water", etc. A photo may have zero or more labels associated with it. See also [labels](#labels).
|
||||
**Note**: Only valid on Photos 5; on earlier versions, returns empty list. In Photos 5, Photos runs machine learning image categorization against photos in the library and automatically assigns labels to photos such as "People", "Dog", "Water", etc. A photo may have zero or more labels associated with it. See also [labels](#photosdb_labels).
|
||||
|
||||
#### `labels_as_dict`
|
||||
|
||||
@ -949,7 +952,7 @@ if __name__ == "__main__":
|
||||
print(photo.original_filename, photo.date)
|
||||
```
|
||||
|
||||
### PhotoInfo
|
||||
### <a name="photoinfo">PhotoInfo</a>
|
||||
|
||||
PhotosDB.photos() returns a list of PhotoInfo objects. Each PhotoInfo object represents a single photo in the Photos library.
|
||||
|
||||
@ -1009,11 +1012,11 @@ Returns a list of [ProjectInfo](#projectinfo) objects representing projects/crea
|
||||
|
||||
Returns a list of the names of the persons in the photo
|
||||
|
||||
#### <a name="photopersoninfo">`person_info`</a>
|
||||
#### <a name="photoinfo_personinfo">`person_info`</a>
|
||||
|
||||
Returns a list of [PersonInfo](#personinfo) objects representing persons in the photo. Each PersonInfo object is associated with one or more FaceInfo objects.
|
||||
|
||||
#### <a name="photofaceinfo">`face_info`</a>
|
||||
#### <a name="photooinfo_faceinfo">`face_info`</a>
|
||||
|
||||
Returns a list of [FaceInfo](#faceinfo) objects representing faces in the photo. Each face is associated with the a PersonInfo object.
|
||||
|
||||
@ -1181,12 +1184,20 @@ Returns True if photo is a [cloud asset](#iscloudasset) and is synched to iCloud
|
||||
|
||||
#### `syndicated`
|
||||
|
||||
Return true if photo was shared via syndication (e.g. via Messages, etc.); these are photos that appear in "Shared with you" album. Photos 8+ only; returns None if not Photos 8+.
|
||||
Return true if photo was shared via syndication (e.g. via Messages, etc.); these are photos that appear in "Shared with you" album. Photos 7+ only; returns None if not Photos 7+.
|
||||
|
||||
#### `saved_to_library`
|
||||
|
||||
Return True if syndicated photo has been saved to library; returns False if photo is not syndicated or has not been saved to the library.
|
||||
Syndicated photos are photos that appear in "Shared with you" album. Photos 8+ only; returns None if not Photos 8+.
|
||||
Syndicated photos are photos that appear in "Shared with you" album. Photos 7+ only; returns None if not Photos 7+.
|
||||
|
||||
#### `shared_moment`
|
||||
|
||||
Return True if photo is part of a shared moment, otherwise False. Shared moments are created when multiple photos are shared via iCloud. (e.g. in Messages)
|
||||
|
||||
#### `shared_library`
|
||||
|
||||
Return True if photo is included in shared iCloud library, otherwise False. Photos 8+ only; returns False if not Photos 8+.
|
||||
|
||||
#### `uti`
|
||||
|
||||
@ -1318,19 +1329,19 @@ for photo in photosdb.photos():
|
||||
|
||||
**Note**: Only valid on Photos 5+; on earlier versions, returns empty list. In Photos 5+, Photos runs machine learning image categorization against photos in the library and automatically assigns labels to photos such as "People", "Dog", "Water", etc. A photo may have zero or more labels associated with it. See also [labels](#labels).
|
||||
|
||||
#### <a name="photosearchinfo">`search_info`</a>
|
||||
#### <a name="photoinfo_searchinfo">`search_info`</a>
|
||||
|
||||
Returns [SearchInfo](#searchinfo) object that represents search metadata for the photo.
|
||||
|
||||
**Note**: Only valid on Photos 5+; on ealier versions, returns None.
|
||||
|
||||
#### <a name="photosearchinfo-normalized">`search_info_normalized`</a>
|
||||
#### <a name="photoinfo_search_info_normalized">`search_info_normalized`</a>
|
||||
|
||||
Returns [SearchInfo](#searchinfo) object that represents normalized search metadata for the photo. This returns a SearchInfo object just as `search_info` but all the properties of the object return normalized text (converted to lowercase).
|
||||
|
||||
**Note**: Only valid on Photos 5+; on ealier versions, returns None.
|
||||
|
||||
#### `exif_info`
|
||||
#### <a name="photoinfo_exif_info">`exif_info`</a>
|
||||
|
||||
Returns an [ExifInfo](#exifinfo) object with EXIF details from the Photos database. See [ExifInfo](#exifinfo) for additional details.
|
||||
|
||||
@ -1338,7 +1349,7 @@ Returns an [ExifInfo](#exifinfo) object with EXIF details from the Photos databa
|
||||
|
||||
See also `exiftool`.
|
||||
|
||||
#### `exiftool`
|
||||
#### <a name="photoinfo_exiftool">`exiftool`</a>
|
||||
|
||||
Returns an [ExifToolCaching](#exiftoolExifTool) object for the photo which provides an interface to [exiftool](https://exiftool.org/) allowing you to read the actual EXIF data in the image file inside the Photos library. If [exif_info](#exif-info) doesn't give you all the data you need, you can use `exiftool` to read the entire EXIF contents of the image.
|
||||
|
||||
@ -1488,7 +1499,7 @@ Some substitutions, notably `album`, `keyword`, and `person` could return multip
|
||||
|
||||
See [Template System](#template-system) for additional details.
|
||||
|
||||
#### <a name="detected_text_method">`detected_text(confidence_threshold=TEXT_DETECTION_CONFIDENCE_THRESHOLD)`</a>
|
||||
#### <a name="photoinfo_detected_text">`detected_text(confidence_threshold=TEXT_DETECTION_CONFIDENCE_THRESHOLD)`</a>
|
||||
|
||||
Detects text in photo and returns lists of results as (detected text, confidence)
|
||||
|
||||
@ -1504,7 +1515,7 @@ See also [Text Detection](#textdetection).
|
||||
|
||||
### ExifInfo
|
||||
|
||||
[PhotosInfo.exif_info](#exif-info) returns an `ExifInfo` object with some EXIF data about the photo (Photos 5 only). `ExifInfo` contains the following properties:
|
||||
[PhotosInfo.exif_info](#photoinfo_exif_info) returns an `ExifInfo` object with some EXIF data about the photo (Photos 5 only). `ExifInfo` contains the following properties:
|
||||
|
||||
```python
|
||||
flash_fired: bool
|
||||
@ -1542,7 +1553,7 @@ nikon_photos = [
|
||||
|
||||
### AlbumInfo
|
||||
|
||||
PhotosDB.album_info and PhotoInfo.album_info return a list of AlbumInfo objects. Each AlbumInfo object represents a single album in the Photos library.
|
||||
[PhotosDB.album_info](#photosdb_album_info) and [PhotoInfo.album_info](photoinfo_album_info) return a list of AlbumInfo objects. Each AlbumInfo object represents a single album in the Photos library.
|
||||
|
||||
#### `uuid`
|
||||
|
||||
@ -1718,11 +1729,11 @@ Returns the universally unique identifier (uuid) of the folder. This is how Pho
|
||||
|
||||
Returns the title or name of the folder.
|
||||
|
||||
#### `album_info`
|
||||
#### <a name="folderinfo_album_info">`album_info`</a>
|
||||
|
||||
Returns a list of [AlbumInfo](#albuminfo) objects representing each album contained in the folder.
|
||||
|
||||
#### `album_info_shared`
|
||||
#### <a name="folderinfo_album_info_shared">`album_info_shared`</a>
|
||||
|
||||
Returns a list of [AlbumInfo](#albuminfo) objects for each shared album in the photos database.
|
||||
|
||||
@ -2033,11 +2044,11 @@ Returns a dictionary representation of the PersonInfo instance.
|
||||
|
||||
[PhotoInfo.face_info](#photofaceinfo) return a list of FaceInfo objects representing detected faces in a photo. The FaceInfo class has the following properties and methods.
|
||||
|
||||
#### `uuid`
|
||||
#### <a name="faceinfo_uuid">`uuid`</a>
|
||||
|
||||
UUID of the face.
|
||||
|
||||
#### `name`
|
||||
#### <a name="faceinfo_name">`name`</a>
|
||||
|
||||
Full name of the person represented by the face or None if person hasn't been given a name in Photos. This is a shortcut for `FaceInfo.person_info.name`.
|
||||
|
||||
@ -2045,11 +2056,11 @@ Full name of the person represented by the face or None if person hasn't been gi
|
||||
|
||||
UUID of the photo this face is associated with.
|
||||
|
||||
#### `person_info`
|
||||
#### <a name="faceinfo_person_info">`person_info`</a>
|
||||
|
||||
[PersonInfo](#personinfo) object associated with this face.
|
||||
|
||||
#### `photo`
|
||||
#### <a name="faceinfo_photo">`photo`</a>
|
||||
|
||||
[PhotoInfo](#photoinfo) object representing the photo that contains this face.
|
||||
|
||||
@ -2126,11 +2137,11 @@ The following additional properties are also available but are not yet fully doc
|
||||
* `lip_makeup_type`:
|
||||
* `smile_type`:
|
||||
|
||||
#### `asdict()`
|
||||
#### <a name="faceinfo_asdict">`asdict()`</a>
|
||||
|
||||
Returns a dictionary representation of the FaceInfo instance.
|
||||
|
||||
#### `json()`
|
||||
#### <a name="faceinfo_json">`json()`</a>
|
||||
|
||||
Returns a JSON representation of the FaceInfo instance.
|
||||
|
||||
@ -2238,8 +2249,9 @@ To get the path of every raw photo, whether it's a single raw photo or a raw+JPE
|
||||
|
||||
<!--[[[cog
|
||||
from osxphotos.phototemplate import get_template_help
|
||||
cog.out(get_template_help())
|
||||
cog.out("\n"+get_template_help())
|
||||
]]]-->
|
||||
|
||||
<!-- Generated by cog: see phototemplate.cog.md -->
|
||||
|
||||
The templating system converts one or template statements, written in osxphotos metadata templating language, to one or more rendered values using information from the photo being processed.
|
||||
@ -2391,9 +2403,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:
|
||||
|
||||
@ -2404,8 +2416,9 @@ The following template field substitutions are availabe for use the templating s
|
||||
|
||||
<!--[[[cog
|
||||
from osxphotos.phototemplate import get_template_field_table
|
||||
cog.out(get_template_field_table())
|
||||
cog.out("\n"+get_template_field_table()+"\n")
|
||||
]]]-->
|
||||
|
||||
| Field | Description |
|
||||
|--------------|-------------|
|
||||
|{name}|Current filename of the photo|
|
||||
@ -2499,7 +2512,7 @@ cog.out(get_template_field_table())
|
||||
|{cr}|A carriage return: '\r'|
|
||||
|{crlf}|A carriage return + line feed: '\r\n'|
|
||||
|{tab}|:A tab: '\t'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.60.7'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.62.1'|
|
||||
|{osxphotos_cmd_line}|The full command line used to run osxphotos|
|
||||
|{album}|Album(s) photo is contained in|
|
||||
|{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder|
|
||||
@ -2691,7 +2704,7 @@ Attributes:
|
||||
|
||||
### <a name="textdetection">Text Detection</a>
|
||||
|
||||
The [PhotoInfo.detected_text()](#detected_text_method) and the `{detected_text}` template will perform text detection on the photos in your library. Text detection is a slow process so to avoid unnecessary re-processing of photos, osxphotos will cache the results of the text detection process as an extended attribute on the photo image file. Extended attributes do not modify the actual file. The extended attribute is named `osxphotos.metadata:detected_text` and can be viewed using the built-in [xattr](https://ss64.com/osx/xattr.html) command or my [osxmetadata](https://github.com/RhetTbull/osxmetadata) tool. If you want to remove the cached attribute, you can do so with `xattr` as follows:
|
||||
The [PhotoInfo.detected_text()](#photoinfo_detected_text) and the `{detected_text}` template will perform text detection on the photos in your library. Text detection is a slow process so to avoid unnecessary re-processing of photos, osxphotos will cache the results of the text detection process as an extended attribute on the photo image file. Extended attributes do not modify the actual file. The extended attribute is named `osxphotos.metadata:detected_text` and can be viewed using the built-in [xattr](https://ss64.com/osx/xattr.html) command or my [osxmetadata](https://github.com/RhetTbull/osxmetadata) tool. If you want to remove the cached attribute, you can do so with `xattr` as follows:
|
||||
|
||||
`find ~/Pictures/Photos\ Library.photoslibrary | xargs -I{} xattr -c osxphotos.metadata:detected_text '{}'`
|
||||
|
||||
|
||||
162
CHANGELOG.md
162
CHANGELOG.md
@ -2,6 +2,168 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [v0.62.1](https://github.com/RhetTbull/osxphotos/compare/v0.62.0...v0.62.1)
|
||||
|
||||
Documentation Fixes
|
||||
|
||||
### [v0.62.1] - 2023-08-13
|
||||
|
||||
#### Changed
|
||||
|
||||
#### Added
|
||||
|
||||
#### Removed
|
||||
|
||||
#### Fixed
|
||||
|
||||
- Minor fixes to the documentation.
|
||||
|
||||
#### Contributors
|
||||
|
||||
- [@RhetTbull](https://github.com/RhetTbull)
|
||||
|
||||
## [v0.62.0](https://github.com/RhetTbull/osxphotos/compare/v0.61.0...v0.62.0)
|
||||
|
||||
Initial support for iCloud Shared Libraries.
|
||||
|
||||
This release contains a lot of changes some of which may be breaking depending on your workflow. If you use `--sidecar-template`, you should look at the help for this option as the options have changed from boolean flags to named flags.
|
||||
|
||||
If you use `--report` with `--append` and you use CSV reports, you should archive the existing report and start a new one as the report now contains additional fields for user files.
|
||||
|
||||
If you use `--post-function`, the called function may now return an [ExportResults](https://rhettbull.github.io/osxphotos/reference.html#osxphotos.ExportResults) object with information about the files written, the files skipped, and any errors generated. If returned, these files will be included in `--report` and will be protected from cleanup with `--cleanup`.
|
||||
|
||||
Initial support for photos in Shared iCloud Libraries has been implemented. These photos can be queried via the `--shared-library` option. Still working on decoding the participant information (who is sharing the photos).
|
||||
|
||||
### [v0.62.0] - 20230812
|
||||
|
||||
#### Added
|
||||
|
||||
- Support for iCloud shared libraries, PhotoInfo.shared_library, PhotoInfo.share_participants, PhotoInfo.share_info (#860)
|
||||
- Shared moment, syndicated, shared library support to `osxphotos inspect`(#860)
|
||||
- `--post-command-error` option to configure error handling of `--post-command` (#1142)
|
||||
- `.osxphotos_keep` file can now be used to specify keep patterns for `--cleanup` (#1135)
|
||||
- Option to `--sidecar-template` to skip zero length files
|
||||
|
||||
#### Removed
|
||||
|
||||
#### Changed
|
||||
|
||||
- Changed `--sidecar-template` options to use named options instead of boolean
|
||||
- Changed signature of --post-function function to enable it to work with --report, --cleanup (#1136)
|
||||
- Now can catch template errors with `catch_errors` option to `--sidecar-template`
|
||||
|
||||
#### Fixed
|
||||
|
||||
- Fixed bug with PhotoInfo.path_raw on Photos <= 4.0
|
||||
|
||||
#### Contributors
|
||||
|
||||
- [@RhetTbull](https://github.com/RhetTbull) - Code and testing
|
||||
- [@neilpa](https://github.com/neilpa) - The idea for custom sidecars and suggestions to improve the feature
|
||||
- [@kvisle](https://github.com/kvisle) - For user testing with iCloud shared libraries
|
||||
|
||||
## [v0.61.0](https://github.com/RhetTbull/osxphotos/compare/v0.60.10...v0.61.0)
|
||||
|
||||
Custom sidecars for osxphotos export
|
||||
|
||||
### [v0.61.0] - 20230725
|
||||
|
||||
#### Added
|
||||
|
||||
- `--sidecar-template` option to export to allow user to specify one or more Mako templates for creating custom sidecars. See [example](https://github.com/RhetTbull/osxphotos/blob/main/examples/custom_sidecar.mako for an example)
|
||||
|
||||
#### Removed
|
||||
|
||||
#### Changed
|
||||
|
||||
- Added `user_sidecar` field to all report formats. This means that if you are using a CSV report with `--append`, you should archive your current report and create a new one which will include the correct headers. For JSON reports, the JSON outpput will simply include a new key for new records. For SQLite reports, the `report` table will be altered to add the new column.
|
||||
|
||||
#### Contributors
|
||||
|
||||
- [@RhetTbull](https://github.com/RhetTbull) - Code and testing
|
||||
- [@neilpa](https://github.com/neilpa) - The idea for custom sidecars
|
||||
|
||||
## [v0.60.10](https://github.com/RhetTbull/osxphotos/compare/v0.60.9...v0.60.10)
|
||||
|
||||
Support for syndicated photos on Monterey (Photos 7)
|
||||
|
||||
### [v0.60.10] - 2023-07-20
|
||||
|
||||
#### Added
|
||||
|
||||
#### Removed
|
||||
|
||||
#### Changed
|
||||
|
||||
- Added additional photo details to `osxphotos debug-dump`
|
||||
|
||||
#### Fixed
|
||||
|
||||
- Syndicated photos now work on Monterey (#1116)
|
||||
- `osxphotos orphans` now also scans the scopes directory
|
||||
|
||||
#### Contributors
|
||||
|
||||
- [@RhetTbull](https://github.com/RhetTbull) - code
|
||||
- [@neilpa](https://github.com/neilpa) - for testing and finding the bug with syndicated photos on Monterey
|
||||
|
||||
## [v0.60.9](https://github.com/RhetTbull/osxphotos/compare/v0.60.8...v0.60.9)
|
||||
|
||||
Fixed missing path for photos that are part of a shared moment (Ventura+)
|
||||
|
||||
### [v0.60.9] - 2023-07-16
|
||||
|
||||
#### Added
|
||||
|
||||
- `PhotoInfo.shared_moment` property (True if photo is part of a shared moment, otherwise False)
|
||||
- `--shared-moment`, `--not-shared-moment` query options
|
||||
|
||||
#### Removed
|
||||
|
||||
#### Changed
|
||||
|
||||
#### Contributors
|
||||
|
||||
- [@RhetTbull](https://github.com/RhetTbull) for code
|
||||
- [@neilpa](https://github.com/neilpa) for identifying the bug with shared moments
|
||||
|
||||
## [v0.60.8](https://github.com/RhetTbull/osxphotos/compare/v0.60.7...v0.60.8)
|
||||
|
||||
Adds support for working with Photos libraries on macOS Sonoma (14.0 preview)
|
||||
|
||||
### [v0.60.8] - 2023-07-16
|
||||
|
||||
#### Added
|
||||
|
||||
- Supports Photos libraries created by Photos 9.0 (macOS Sonoma)
|
||||
|
||||
#### Removed
|
||||
|
||||
#### Changed
|
||||
|
||||
#### Contributors
|
||||
|
||||
- [@RhetTbull](https://github.com/RhetTbull) - code changes and testing
|
||||
|
||||
## [v0.60.7](https://github.com/RhetTbull/osxphotos/compare/v0.60.6...v0.60.7)
|
||||
|
||||
AAE Export Support
|
||||
|
||||
### [v0.60.7] - 2023-07-15
|
||||
|
||||
#### Addeded
|
||||
|
||||
- `--export-aae` option for `osxphotos export` to export the raw adjustments plist files
|
||||
- `PhotoInfo.adjustments_path` property for retrieving the path to the AAE file
|
||||
|
||||
#### Removed
|
||||
|
||||
#### Changed
|
||||
|
||||
#### Contributors
|
||||
|
||||
- [@dvdkon](https://github.com/dvdkon) - code changes to add support for AAE files.
|
||||
|
||||
## [v0.60.6](https://github.com/RhetTbull/osxphotos/compare/v0.60.5...v0.60.6)
|
||||
|
||||
Remove --library/--db from import command
|
||||
|
||||
188
README.md
188
README.md
@ -39,10 +39,12 @@ On Linux, macOS-specific features of the CLI will not be available (these will n
|
||||
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.3). Tested on both x86 and Apple silicon (M1).
|
||||
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 |
|
||||
| ----------------- |------------|:-------------------|
|
||||
| 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 ✅ |
|
||||
@ -880,6 +882,14 @@ Options:
|
||||
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
|
||||
--shared-library Search for photos that are part of a shared
|
||||
library
|
||||
--not-shared-library Search for photos that are not part of a
|
||||
shared library
|
||||
--regex REGEX TEMPLATE Search for photos where TEMPLATE matches
|
||||
regular expression REGEX. For example, to find
|
||||
photos in an album that begins with 'Beach': '
|
||||
@ -1111,6 +1121,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
|
||||
@ -1291,30 +1356,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
|
||||
@ -1358,8 +1452,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
|
||||
@ -1781,19 +1885,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
|
||||
@ -2118,7 +2223,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.60.7'
|
||||
{osxphotos_version} The osxphotos version, e.g. '0.62.1'
|
||||
{osxphotos_cmd_line} The full command line used to run osxphotos
|
||||
|
||||
The following substitutions may result in multiple values. Thus if specified
|
||||
@ -2341,6 +2446,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
|
||||
|
||||
@ -2500,9 +2606,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:
|
||||
|
||||
@ -2605,7 +2711,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.60.7'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.62.1'|
|
||||
|{osxphotos_cmd_line}|The full command line used to run osxphotos|
|
||||
|{album}|Album(s) photo is contained in|
|
||||
|{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder|
|
||||
@ -2679,7 +2785,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>
|
||||
|
||||
6
build.sh
6
build.sh
@ -30,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)
|
||||
|
||||
@ -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: b4797f5f0cba9ef01218a6f2b8eb0959
|
||||
config: 2fc476010affcee784f205bf294f4e73
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
|
||||
1735
docs/API_README.html
1735
docs/API_README.html
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.60.7 documentation</title>
|
||||
<title>Overview: module code - osxphotos 0.62.1 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.60.7 documentation</div></a>
|
||||
<a href="../index.html"><div class="brand">osxphotos 0.62.1 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.60.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.1 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,6 +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="../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>
|
||||
|
||||
|
||||
@ -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.60.5 documentation</title>
|
||||
<title>osxphotos._constants - osxphotos 0.62.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.60.5 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.62.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.60.5 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.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,6 +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="../../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>
|
||||
|
||||
@ -220,15 +221,18 @@
|
||||
<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>
|
||||
|
||||
@ -236,7 +240,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>
|
||||
@ -244,8 +248,15 @@
|
||||
<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"># shared iCloud library versions; dev preview doesn't contain same columns as release version</span>
|
||||
<span class="n">_PHOTOS_SHARED_LIBRARY_VERSION</span> <span class="o">=</span> <span class="mi">16320</span> <span class="c1"># 13.0</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>
|
||||
@ -258,6 +269,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>
|
||||
@ -270,6 +283,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>
|
||||
@ -282,6 +297,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>
|
||||
@ -294,6 +311,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>
|
||||
|
||||
@ -324,6 +357,7 @@
|
||||
<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>
|
||||
|
||||
@ -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.59.2 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.59.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.59.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">
|
||||
|
||||
@ -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.58.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.58.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.58.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">
|
||||
|
||||
@ -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.59.1 documentation</title>
|
||||
<title>osxphotos.exiftool - osxphotos 0.62.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.59.1 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.62.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.59.1 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.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,6 +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="../../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>
|
||||
|
||||
@ -255,7 +256,7 @@
|
||||
|
||||
<span class="k">def</span> <span class="nf">escape_str</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
|
||||
<span class="sd">"""escape string for use with exiftool -E"""</span>
|
||||
<span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">str</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">s</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="n">s</span>
|
||||
<span class="n">s</span> <span class="o">=</span> <span class="n">html</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
|
||||
<span class="n">s</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="s2">"&#xa;"</span><span class="p">)</span>
|
||||
@ -266,7 +267,7 @@
|
||||
|
||||
<span class="k">def</span> <span class="nf">unescape_str</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
|
||||
<span class="sd">"""unescape an HTML string returned by exiftool -E"""</span>
|
||||
<span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">str</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">s</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="n">s</span>
|
||||
<span class="c1"># avoid " in values which result in json.loads() throwing an exception, #636</span>
|
||||
<span class="n">s</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"&quot;"</span><span class="p">,</span> <span class="s1">'</span><span class="se">\\</span><span class="s1">"'</span><span class="p">)</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.export_db - osxphotos 0.60.5 documentation</title>
|
||||
<title>osxphotos.export_db - 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.60.5 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.60.5 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">
|
||||
|
||||
@ -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.60.5 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.60.5 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.60.5 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">
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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.personinfo - osxphotos 0.58.1 documentation</title>
|
||||
<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=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.58.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.58.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">
|
||||
@ -334,7 +334,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></div>
|
||||
|
||||
|
||||
<span class="k">class</span> <span class="nc">FaceInfo</span><span class="p">:</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>
|
||||
@ -472,7 +472,7 @@
|
||||
|
||||
<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>
|
||||
<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>
|
||||
@ -486,16 +486,16 @@
|
||||
<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>
|
||||
<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="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>
|
||||
@ -598,7 +598,7 @@
|
||||
|
||||
<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>
|
||||
<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>
|
||||
@ -633,11 +633,11 @@
|
||||
<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="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>
|
||||
<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>
|
||||
<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>
|
||||
@ -654,7 +654,7 @@
|
||||
<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>
|
||||
|
||||
@ -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.60.7 documentation</title>
|
||||
<title>osxphotos.photoexporter - osxphotos 0.62.1 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.60.7 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.62.1 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.60.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.1 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,6 +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="../../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>
|
||||
|
||||
@ -463,7 +464,51 @@
|
||||
|
||||
|
||||
<div class="viewcode-block" id="ExportResults"><a class="viewcode-back" href="../../reference.html#osxphotos.ExportResults">[docs]</a><span class="k">class</span> <span class="nc">ExportResults</span><span class="p">:</span>
|
||||
<span class="sd">"""Results class which holds export results for export"""</span>
|
||||
<span class="sd">"""Results class which holds export results for export</span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> Args:</span>
|
||||
<span class="sd"> converted_to_jpeg: list of files converted to jpeg</span>
|
||||
<span class="sd"> deleted_directories: list of directories deleted</span>
|
||||
<span class="sd"> deleted_files: list of files deleted</span>
|
||||
<span class="sd"> error: list of tuples of (filename, error) for any errors generated during export</span>
|
||||
<span class="sd"> exif_updated: list of files where exif data was updated with exiftool</span>
|
||||
<span class="sd"> exiftool_error: list of tuples of (filename, error) for any errors generated by exiftool</span>
|
||||
<span class="sd"> exiftool_warning: list of tuples of (filename, warning) for any warnings generated by exiftool</span>
|
||||
<span class="sd"> exported: list of files exported</span>
|
||||
<span class="sd"> exported_album: list of tuples of (file, album) for any files exported to an album</span>
|
||||
<span class="sd"> metadata_changed: list of filenames that had metadata changes since last export</span>
|
||||
<span class="sd"> missing: list of files that were missing</span>
|
||||
<span class="sd"> missing_album: list of tuples of (file, album) for any files that were missing from an album</span>
|
||||
<span class="sd"> new: list of files that were new</span>
|
||||
<span class="sd"> aae_written: list of files where .AAE file was written</span>
|
||||
<span class="sd"> sidecar_exiftool_skipped: list of files where exiftool sidecar was skipped</span>
|
||||
<span class="sd"> sidecar_exiftool_written: list of files where exiftool sidecar was written</span>
|
||||
<span class="sd"> sidecar_json_skipped: list of files where json sidecar was skipped</span>
|
||||
<span class="sd"> sidecar_json_written: list of files where json sidecar was written</span>
|
||||
<span class="sd"> sidecar_xmp_skipped: list of files where xmp sidecar was skipped</span>
|
||||
<span class="sd"> sidecar_xmp_written: list of files where xmp sidecar was written</span>
|
||||
<span class="sd"> sidecar_user_written: list of files where user sidecar was written</span>
|
||||
<span class="sd"> sidecar_user_skipped: list of files where user sidecar was skipped</span>
|
||||
<span class="sd"> sidecar_user_error: list of tuples of (filename, error) for any errors generated by user sidecar</span>
|
||||
<span class="sd"> skipped: list of files that were skipped</span>
|
||||
<span class="sd"> skipped_album: list of tuples of (file, album) for any files that were skipped from an album</span>
|
||||
<span class="sd"> to_touch: list of files that were touched</span>
|
||||
<span class="sd"> touched: list of files that were touched</span>
|
||||
<span class="sd"> updated: list of files that were updated</span>
|
||||
<span class="sd"> xattr_skipped: list of files where xattr was skipped</span>
|
||||
<span class="sd"> xattr_written: list of files where xattr was written</span>
|
||||
<span class="sd"> user_written: list of files written by user post_function</span>
|
||||
<span class="sd"> user_skipped: list of files skipped by user post_function</span>
|
||||
<span class="sd"> user_error: list of tuples of (filename, error) for any errors generated by user post_function</span>
|
||||
|
||||
<span class="sd"> Notes:</span>
|
||||
<span class="sd"> Each attribute is a list of files or None if no files for that attribute.</span>
|
||||
<span class="sd"> Error and warning attributes are a list of tuples of (filename, error) where filename is the file that caused the error and error is the error message.</span>
|
||||
<span class="sd"> Album attributes are a list of tuples of (file, album) where file is the file exported and album is the album it was exported to.</span>
|
||||
<span class="sd"> ExportResults can be added together with the += operator to combine results as the export progresses.</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="c1"># Note: __init__ docs above added in the class docstring so they are picked up by sphinx</span>
|
||||
|
||||
<span class="vm">__slots__</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="s2">"_datetime"</span><span class="p">,</span>
|
||||
@ -487,6 +532,9 @@
|
||||
<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>
|
||||
@ -494,38 +542,51 @@
|
||||
<span class="s2">"updated"</span><span class="p">,</span>
|
||||
<span class="s2">"xattr_skipped"</span><span class="p">,</span>
|
||||
<span class="s2">"xattr_written"</span><span class="p">,</span>
|
||||
<span class="s2">"user_written"</span><span class="p">,</span>
|
||||
<span class="s2">"user_skipped"</span><span class="p">,</span>
|
||||
<span class="s2">"user_error"</span><span class="p">,</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">converted_to_jpeg</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">deleted_directories</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">deleted_files</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">error</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">exif_updated</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">exiftool_error</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">exiftool_warning</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">exported</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">exported_album</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">metadata_changed</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<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">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>
|
||||
<span class="n">touched</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">updated</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
||||
<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="n">converted_to_jpeg</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">deleted_directories</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">deleted_files</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">error</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">exif_updated</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">exiftool_error</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">tuple</span><span class="p">[</span><span class="nb">str</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">exiftool_warning</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">tuple</span><span class="p">[</span><span class="nb">str</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">exported</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">exported_album</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">tuple</span><span class="p">[</span><span class="nb">str</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">metadata_changed</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">missing</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">missing_album</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">tuple</span><span class="p">[</span><span class="nb">str</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">new</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">aae_written</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_exiftool_skipped</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_exiftool_written</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_json_skipped</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_json_written</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_xmp_skipped</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_xmp_written</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_user_written</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_user_skipped</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">sidecar_user_error</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">tuple</span><span class="p">[</span><span class="nb">str</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">skipped</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">skipped_album</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">tuple</span><span class="p">[</span><span class="nb">str</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">to_touch</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">touched</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">updated</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">xattr_skipped</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">xattr_written</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">user_written</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">user_skipped</span><span class="p">:</span> <span class="nb">list</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="n">user_error</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">tuple</span><span class="p">[</span><span class="nb">str</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="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
||||
<span class="p">):</span>
|
||||
<span class="sd">"""ExportResults data class to hold results of export.</span>
|
||||
|
||||
<span class="sd"> See class docstring for details.</span>
|
||||
<span class="sd"> """</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>
|
||||
@ -558,11 +619,17 @@
|
||||
<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="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">user_written</span>
|
||||
<span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">user_skipped</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="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">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>
|
||||
|
||||
@ -1630,7 +1697,8 @@
|
||||
<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="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>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos.photoinfo - osxphotos 0.60.7 documentation</title>
|
||||
<title>osxphotos.photoinfo - osxphotos 0.62.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.60.7 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.62.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.60.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.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,6 +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="../../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>
|
||||
|
||||
@ -262,6 +263,8 @@
|
||||
<span class="kn">from</span> <span class="nn">.query_builder</span> <span class="kn">import</span> <span class="n">get_query</span>
|
||||
<span class="kn">from</span> <span class="nn">.scoreinfo</span> <span class="kn">import</span> <span class="n">ScoreInfo</span>
|
||||
<span class="kn">from</span> <span class="nn">.searchinfo</span> <span class="kn">import</span> <span class="n">SearchInfo</span>
|
||||
<span class="kn">from</span> <span class="nn">.shareinfo</span> <span class="kn">import</span> <span class="n">ShareInfo</span><span class="p">,</span> <span class="n">get_moment_share_info</span><span class="p">,</span> <span class="n">get_share_info</span>
|
||||
<span class="kn">from</span> <span class="nn">.shareparticipant</span> <span class="kn">import</span> <span class="n">ShareParticipant</span><span class="p">,</span> <span class="n">get_share_participants</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="p">,</span> <span class="n">get_uti_for_extension</span>
|
||||
<span class="kn">from</span> <span class="nn">.utils</span> <span class="kn">import</span> <span class="n">_get_resource_loc</span><span class="p">,</span> <span class="n">hexdigest</span><span class="p">,</span> <span class="n">list_directory</span>
|
||||
|
||||
@ -370,6 +373,16 @@
|
||||
<span class="sd">"""Returns candidate path for original photo on Photos >= version 5"""</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_info</span><span class="p">[</span><span class="s2">"shared"</span><span class="p">]:</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_path_5_shared</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="p">(</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">shared_moment</span>
|
||||
<span class="ow">and</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">7</span>
|
||||
<span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_path_shared_moment</span><span class="p">()</span>
|
||||
<span class="p">):</span>
|
||||
<span class="c1"># path for photos in shared moments if it's in the shared moment folder</span>
|
||||
<span class="c1"># the file may also be in the originals folder which the next check will catch</span>
|
||||
<span class="c1"># check shared_moment first as a photo can be both a shared moment and syndicated</span>
|
||||
<span class="c1"># and if so, will be in the shared moment folder</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_path_shared_moment</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">syndicated</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">saved_to_library</span><span class="p">:</span>
|
||||
<span class="c1"># path for "shared with you" syndicated photos that have not yet been saved to the library</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_path_syndication</span><span class="p">()</span>
|
||||
@ -413,8 +426,8 @@
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_path_syndication</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return path for syndicated photo on Photos >= version 8"""</span>
|
||||
<span class="c1"># Photos 8+ stores syndicated photos in a separate directory</span>
|
||||
<span class="sd">"""Return path for syndicated photo on Photos >= version 7"""</span>
|
||||
<span class="c1"># Photos 7+ stores syndicated photos in a separate directory</span>
|
||||
<span class="c1"># in ~/Photos Library.photoslibrary/scopes/syndication/originals/X/UUID.ext</span>
|
||||
<span class="c1"># where X is first digit of UUID</span>
|
||||
<span class="n">syndication_path</span> <span class="o">=</span> <span class="s2">"scopes/syndication/originals"</span>
|
||||
@ -427,6 +440,21 @@
|
||||
<span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">path</span> <span class="k">if</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">path</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_path_shared_moment</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return path for shared moment photo on Photos >= version 7"""</span>
|
||||
<span class="c1"># Photos 7+ stores shared moment photos in a separate directory</span>
|
||||
<span class="c1"># in ~/Photos Library.photoslibrary/scopes/momentshared/originals/X/UUID.ext</span>
|
||||
<span class="c1"># where X is first digit of UUID</span>
|
||||
<span class="n">momentshared_path</span> <span class="o">=</span> <span class="s2">"scopes/momentshared/originals"</span>
|
||||
<span class="n">uuid_dir</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="mi">0</span><span class="p">]</span>
|
||||
<span class="n">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="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_library_path</span><span class="p">,</span>
|
||||
<span class="n">momentshared_path</span><span class="p">,</span>
|
||||
<span class="n">uuid_dir</span><span class="p">,</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">,</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">path</span> <span class="k">if</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">path</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_path_4</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Returns candidate path for original photo on Photos <= version 4"""</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_info</span><span class="p">[</span><span class="s2">"has_raw"</span><span class="p">]:</span>
|
||||
@ -547,7 +575,7 @@
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_path_edited_4</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">"""return path_edited for Photos <= 4; modified version of code in PhotoInfo to debug #859"""</span>
|
||||
<span class="sd">"""return path_edited for Photos <= 4; #859"""</span>
|
||||
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_info</span><span class="p">[</span><span class="s2">"hasAdjustments"</span><span class="p">]:</span>
|
||||
<span class="k">return</span> <span class="kc">None</span>
|
||||
@ -652,7 +680,7 @@
|
||||
|
||||
<span class="c1"># In Photos 5, raw is in same folder as original but with _4.ext</span>
|
||||
<span class="c1"># Unless "Copy Items to the Photos Library" is not checked</span>
|
||||
<span class="c1"># then RAW image is not renamed but has same name is jpeg buth with raw extension</span>
|
||||
<span class="c1"># then RAW image is not renamed but has same name is jpeg but with raw extension</span>
|
||||
<span class="c1"># Current implementation finds images with the correct raw UTI extension</span>
|
||||
<span class="c1"># in same folder as the original and with same stem as original in form: original_stem*.raw_ext</span>
|
||||
<span class="c1"># TODO: I don't like this -- would prefer a more deterministic approach but until I have more</span>
|
||||
@ -722,6 +750,7 @@
|
||||
<span class="sa">f</span><span class="s2">"MISSING PATH: RAW photo for 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"> should be at </span><span class="si">{</span><span class="n">photopath</span><span class="si">}</span><span class="s2"> but does not appear to exist"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">photopath</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
<span class="k">return</span> <span class="n">photopath</span>
|
||||
|
||||
<span class="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">description</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
@ -1107,6 +1136,8 @@
|
||||
<span class="k">elif</span> <span class="bp">self</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">path</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">ismissing</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">shared</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_path_live_photo_shared_5</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">shared_moment</span> <span class="ow">and</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">7</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_path_live_shared_moment</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">syndicated</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">saved_to_library</span><span class="p">:</span>
|
||||
<span class="c1"># syndicated ("Shared with you") photos not yet saved to library</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_path_live_syndicated</span><span class="p">()</span>
|
||||
@ -1169,8 +1200,8 @@
|
||||
<span class="k">return</span> <span class="n">photopath</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_path_live_syndicated</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return path for live syndicated photo on Photos >= version 8"""</span>
|
||||
<span class="c1"># Photos 8+ stores live syndicated photos in a separate directory</span>
|
||||
<span class="sd">"""Return path for live syndicated photo on Photos >= version 7"""</span>
|
||||
<span class="c1"># Photos 7+ stores live syndicated photos in a separate directory</span>
|
||||
<span class="c1"># in ~/Photos Library.photoslibrary/scopes/syndication/originals/X/UUID_3.mov</span>
|
||||
<span class="c1"># where X is first digit of UUID</span>
|
||||
<span class="n">syndication_path</span> <span class="o">=</span> <span class="s2">"scopes/syndication/originals"</span>
|
||||
@ -1184,6 +1215,22 @@
|
||||
<span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">live_photo</span> <span class="k">if</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">live_photo</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">_path_live_shared_moment</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""Return path for live shared moment photo on Photos >= version 7"""</span>
|
||||
<span class="c1"># Photos 7+ stores live shared moment photos in a separate directory</span>
|
||||
<span class="c1"># in ~/Photos Library.photoslibrary/scopes/momentshared/originals/X/UUID_3.mov</span>
|
||||
<span class="c1"># where X is first digit of UUID</span>
|
||||
<span class="n">shared_moment_path</span> <span class="o">=</span> <span class="s2">"scopes/momentshared/originals"</span>
|
||||
<span class="n">uuid_dir</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="mi">0</span><span class="p">]</span>
|
||||
<span class="n">filename</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</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">filename</span><span class="p">)</span><span class="o">.</span><span class="n">stem</span><span class="si">}</span><span class="s2">_3.mov"</span>
|
||||
<span class="n">live_photo</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="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_library_path</span><span class="p">,</span>
|
||||
<span class="n">shared_moment_path</span><span class="p">,</span>
|
||||
<span class="n">uuid_dir</span><span class="p">,</span>
|
||||
<span class="n">filename</span><span class="p">,</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">live_photo</span> <span class="k">if</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">live_photo</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
|
||||
|
||||
<span class="nd">@cached_property</span>
|
||||
<span class="k">def</span> <span class="nf">path_derivatives</span><span class="p">(</span><span class="bp">self</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">"""Return any derivative (preview) images associated with the photo as a list of paths, sorted by file size (largest first)"""</span>
|
||||
@ -1194,19 +1241,29 @@
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_path_derivatives_5_shared</span><span class="p">()</span>
|
||||
|
||||
<span class="n">directory</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="mi">0</span><span class="p">]</span> <span class="c1"># first char of uuid</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">syndicated</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">saved_to_library</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">shared_moment</span> <span class="ow">and</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">7</span><span class="p">:</span>
|
||||
<span class="c1"># shared moments</span>
|
||||
<span class="n">derivative_path</span> <span class="o">=</span> <span class="s2">"scopes/momentshared/resources/derivatives"</span>
|
||||
<span class="n">thumb_path</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">derivative_path</span><span class="si">}</span><span class="s2">/masters/</span><span class="si">{</span><span class="n">directory</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="si">}</span><span class="s2">_4_5005_c.jpeg"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">syndicated</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">saved_to_library</span><span class="p">:</span>
|
||||
<span class="c1"># syndicated ("Shared with you") photos not yet saved to library</span>
|
||||
<span class="n">derivative_path</span> <span class="o">=</span> <span class="s2">"scopes/syndication/resources/derivatives"</span>
|
||||
<span class="n">thumb_path</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">derivative_path</span><span class="si">}</span><span class="s2">/masters/</span><span class="si">{</span><span class="n">directory</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="si">}</span><span class="s2">_4_5005_c.jpeg"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">derivative_path</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"resources/derivatives/</span><span class="si">{</span><span class="n">directory</span><span class="si">}</span><span class="s2">"</span>
|
||||
<span class="n">derivative_path</span> <span class="o">=</span> <span class="s2">"resources/derivatives"</span>
|
||||
<span class="n">thumb_path</span> <span class="o">=</span> <span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"resources/derivatives/masters/</span><span class="si">{</span><span class="n">directory</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="si">}</span><span class="s2">_4_5005_c.jpeg"</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="n">derivative_path</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">_db</span><span class="o">.</span><span class="n">_library_path</span><span class="p">)</span><span class="o">.</span><span class="n">joinpath</span><span class="p">(</span><span class="n">derivative_path</span><span class="p">)</span>
|
||||
<span class="n">derivative_path</span> <span class="o">=</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="bp">self</span><span class="o">.</span><span class="n">_db</span><span class="o">.</span><span class="n">_library_path</span><span class="p">)</span>
|
||||
<span class="o">.</span><span class="n">joinpath</span><span class="p">(</span><span class="n">derivative_path</span><span class="p">)</span>
|
||||
<span class="o">.</span><span class="n">joinpath</span><span class="p">(</span><span class="n">directory</span><span class="p">)</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">thumb_path</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">_db</span><span class="o">.</span><span class="n">_library_path</span><span class="p">)</span><span class="o">.</span><span class="n">joinpath</span><span class="p">(</span><span class="n">thumb_path</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># find all files that start with uuid in derivative path</span>
|
||||
@ -1546,9 +1603,9 @@
|
||||
<span class="k">def</span> <span class="nf">syndicated</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="o">|</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="sd">"""Return true if photo was shared via syndication (e.g. via Messages, etc.);</span>
|
||||
<span class="sd"> these are photos that appear in "Shared with you" album.</span>
|
||||
<span class="sd"> Photos 8+ only; returns None if not Photos 8+.</span>
|
||||
<span class="sd"> Photos 7+ only; returns None if not Photos 7+.</span>
|
||||
<span class="sd"> """</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">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">7</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="kc">None</span>
|
||||
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
@ -1563,10 +1620,10 @@
|
||||
<span class="k">def</span> <span class="nf">saved_to_library</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="o">|</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="sd">"""Return True if syndicated photo has been saved to library;</span>
|
||||
<span class="sd"> returns False if photo is not syndicated or has not been saved to the library.</span>
|
||||
<span class="sd"> Returns None if not Photos 8+.</span>
|
||||
<span class="sd"> Syndicated photos are photos that appear in "Shared with you" album; Photos 8+ only.</span>
|
||||
<span class="sd"> Returns None if not Photos 7+.</span>
|
||||
<span class="sd"> Syndicated photos are photos that appear in "Shared with you" album; Photos 7+ only.</span>
|
||||
<span class="sd"> """</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">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">7</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="kc">None</span>
|
||||
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
@ -1574,6 +1631,46 @@
|
||||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="kc">False</span>
|
||||
|
||||
<span class="nd">@cached_property</span>
|
||||
<span class="k">def</span> <span class="nf">shared_moment</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 is part of a shared moment otherwise False (Photos 7+ only)"""</span>
|
||||
<span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_info</span><span class="p">[</span><span class="s2">"moment_share"</span><span class="p">])</span>
|
||||
|
||||
<span class="nd">@cached_property</span>
|
||||
<span class="k">def</span> <span class="nf">shared_moment_info</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">ShareInfo</span> <span class="o">|</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="sd">"""Returns ShareInfo object with information about the shared moment the photo is part of (Photos 7+ only)"""</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">7</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="kc">None</span>
|
||||
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="n">get_moment_share_info</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_db</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">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="kc">None</span>
|
||||
|
||||
<span class="nd">@cached_property</span>
|
||||
<span class="k">def</span> <span class="nf">share_info</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">ShareInfo</span> <span class="o">|</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="sd">"""Returns ShareInfo object with information about the shared photo in a shared iCloud library (Photos 8+ only) (currently experimental)"""</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">None</span>
|
||||
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="n">get_share_info</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_db</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">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="kc">None</span>
|
||||
|
||||
<span class="nd">@cached_property</span>
|
||||
<span class="k">def</span> <span class="nf">shared_library</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 is in a shared iCloud library otherwise False (Photos 8+ only)"""</span>
|
||||
<span class="c1"># TODO: this is just a guess right now as I don't currently use shared libraries</span>
|
||||
<span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_info</span><span class="p">[</span><span class="s2">"active_library_participation_state"</span><span class="p">])</span>
|
||||
|
||||
<span class="nd">@cached_property</span>
|
||||
<span class="k">def</span> <span class="nf">share_participants</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">list</span><span class="p">[</span><span class="n">ShareParticipant</span><span class="p">]:</span>
|
||||
<span class="sd">"""Returns list of ShareParticpant objects with information on who the photo is shared with (Photos 8+ only)"""</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="p">[]</span>
|
||||
<span class="k">return</span> <span class="n">get_share_participants</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_db</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="nd">@property</span>
|
||||
<span class="k">def</span> <span class="nf">labels</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">"""returns list of labels applied to photo by Photos image categorization</span>
|
||||
@ -2076,6 +2173,10 @@
|
||||
<span class="n">place</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">place</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">place</span> <span class="k">else</span> <span class="p">{}</span>
|
||||
<span class="n">score</span> <span class="o">=</span> <span class="n">dataclasses</span><span class="o">.</span><span class="n">asdict</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">score</span><span class="p">)</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">score</span> <span class="k">else</span> <span class="p">{}</span>
|
||||
|
||||
<span class="c1"># do not add any new properties to data_dict as this is used by export to determine</span>
|
||||
<span class="c1"># if a photo needs to be re-exported and adding new properties may cause all photos</span>
|
||||
<span class="c1"># to be re-exported</span>
|
||||
<span class="c1"># see below `if not shallow:`</span>
|
||||
<span class="n">dict_data</span> <span class="o">=</span> <span class="p">{</span>
|
||||
<span class="s2">"albums"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">albums</span><span class="p">,</span>
|
||||
<span class="s2">"burst"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">burst</span><span class="p">,</span>
|
||||
@ -2150,6 +2251,7 @@
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="c1"># non-shallow keys</span>
|
||||
<span class="c1"># add any new properties here</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">shallow</span><span class="p">:</span>
|
||||
<span class="n">dict_data</span><span class="p">[</span><span class="s2">"album_info"</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">album</span><span class="o">.</span><span class="n">asdict</span><span class="p">()</span> <span class="k">for</span> <span class="n">album</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">album_info</span><span class="p">]</span>
|
||||
<span class="n">dict_data</span><span class="p">[</span><span class="s2">"path_derivatives"</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">path_derivatives</span>
|
||||
@ -2177,6 +2279,10 @@
|
||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">search_info_normalized</span>
|
||||
<span class="k">else</span> <span class="p">{}</span>
|
||||
<span class="p">)</span>
|
||||
<span class="n">dict_data</span><span class="p">[</span><span class="s2">"syndicated"</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">syndicated</span>
|
||||
<span class="n">dict_data</span><span class="p">[</span><span class="s2">"saved_to_library"</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">saved_to_library</span>
|
||||
<span class="n">dict_data</span><span class="p">[</span><span class="s2">"shared_moment"</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">shared_moment</span>
|
||||
<span class="n">dict_data</span><span class="p">[</span><span class="s2">"shared_library"</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">shared_library</span>
|
||||
|
||||
<span class="k">return</span> <span class="n">dict_data</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.photosalbum - osxphotos 0.60.5 documentation</title>
|
||||
<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=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.60.5 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.60.5 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">
|
||||
|
||||
@ -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_process_comments - osxphotos 0.60.5 documentation</title>
|
||||
<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=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.60.5 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.60.5 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">
|
||||
|
||||
@ -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.60.5 documentation</title>
|
||||
<title>osxphotos.photosdb.photosdb - osxphotos 0.62.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.60.5 documentation</div></a>
|
||||
<a href="../../../index.html"><div class="brand">osxphotos 0.62.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.60.5 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.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,6 +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="../../../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>
|
||||
|
||||
@ -259,7 +260,11 @@
|
||||
<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">..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_db_model_version</span><span class="p">,</span> <span class="n">get_db_version</span>
|
||||
<span class="kn">from</span> <span class="nn">.photosdb_utils</span> <span class="kn">import</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="p">,</span>
|
||||
<span class="n">get_photos_version_from_model</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>
|
||||
@ -288,6 +293,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_shared_library</span> <span class="kn">import</span> <span class="n">_process_shared_library_info</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>
|
||||
@ -483,7 +489,7 @@
|
||||
<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"># Dict to hold syndication info for Photos >= 7</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>
|
||||
|
||||
@ -523,7 +529,7 @@
|
||||
<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>
|
||||
@ -538,21 +544,23 @@
|
||||
<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>
|
||||
<span class="n">dbpath</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">_dbfile</span><span class="p">)</span><span class="o">.</span><span class="n">parent</span>
|
||||
<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="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>
|
||||
@ -1432,6 +1440,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>
|
||||
@ -1744,6 +1755,12 @@
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"UTI_raw"</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">"raw_pair_info"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
<span class="c1"># placeholders for shared library info on Photos 8+</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">_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">"active_library_participation_state"</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">"library_scope_share_state"</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">"library_scope"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
<span class="c1"># done with the database connection</span>
|
||||
<span class="n">conn</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||||
|
||||
@ -1903,6 +1920,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>
|
||||
@ -1911,7 +1929,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>
|
||||
|
||||
@ -1930,13 +1948,14 @@
|
||||
|
||||
<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>
|
||||
|
||||
@ -2144,7 +2163,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>
|
||||
@ -2195,6 +2215,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>
|
||||
@ -2382,6 +2403,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>
|
||||
@ -2406,6 +2429,11 @@
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"UTI_edited_photo"</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_edited_video"</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
||||
<span class="c1"># placeholder for shared library info (Photos 8+)</span>
|
||||
<span class="n">info</span><span class="p">[</span><span class="s2">"active_library_participation_state"</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">"library_scope_share_state"</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">"library_scope"</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="o">=</span> <span class="n">info</span>
|
||||
|
||||
<span class="c1"># compute signatures for finding possible duplicates</span>
|
||||
@ -2714,10 +2742,14 @@
|
||||
<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">8</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="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">8</span><span class="p">:</span>
|
||||
<span class="n">verbose</span><span class="p">(</span><span class="s2">"Processing shared iCloud library info"</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">_process_shared_library_info</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>
|
||||
@ -3727,6 +3759,16 @@
|
||||
<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">shared_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">shared_library</span><span class="p">]</span>
|
||||
<span class="k">elif</span> <span class="n">options</span><span class="o">.</span><span class="n">not_shared_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="ow">not</span> <span class="n">p</span><span class="o">.</span><span class="n">shared_library</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>
|
||||
|
||||
@ -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.phototemplate - osxphotos 0.60.0 documentation</title>
|
||||
<title>osxphotos.phototemplate - osxphotos 0.62.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.60.0 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.62.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.60.0 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.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,6 +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="../../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>
|
||||
|
||||
@ -661,7 +662,7 @@
|
||||
<span class="sd"> ([rendered_strings], [unmatched]): tuple of list of rendered strings and list of unmatched template values</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">template</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="nb">str</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">template</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
||||
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"template must be type str, not </span><span class="si">{</span><span class="nb">type</span><span class="p">(</span><span class="n">template</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">options</span> <span class="o">=</span> <span class="n">options</span>
|
||||
@ -1592,7 +1593,7 @@
|
||||
<span class="c1"># if no uuid, then template is being validated but not actually run</span>
|
||||
<span class="c1"># so don't run the function</span>
|
||||
<span class="n">values</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">elif</span> <span class="n">caller</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"export"</span><span class="p">,</span> <span class="s2">"query"</span><span class="p">]:</span>
|
||||
<span class="k">elif</span> <span class="n">caller</span> <span class="ow">in</span> <span class="p">{</span><span class="s2">"export"</span><span class="p">,</span> <span class="s2">"query"</span><span class="p">}:</span>
|
||||
<span class="c1"># function signature is:</span>
|
||||
<span class="c1"># def example(photo: PhotoInfo, options: ExportOptions, args: Optional[str] = None, **kwargs) -> Union[List, str]:</span>
|
||||
<span class="n">values</span> <span class="o">=</span> <span class="n">template_func</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="n">options</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="n">field_arg</span><span class="p">)</span>
|
||||
@ -1608,7 +1609,7 @@
|
||||
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
||||
<span class="sa">f</span><span class="s2">"Invalid return type for function </span><span class="si">{</span><span class="n">funcname</span><span class="si">}</span><span class="s2">: expected str or list"</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">values</span><span class="p">)</span> <span class="o">==</span> <span class="nb">str</span><span class="p">:</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">str</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="c1"># sanitize directory names if needed</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.placeinfo - osxphotos 0.60.7 documentation</title>
|
||||
<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=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.60.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.60.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">
|
||||
|
||||
@ -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.queryoptions - osxphotos 0.60.5 documentation</title>
|
||||
<title>osxphotos.queryoptions - osxphotos 0.62.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.60.5 documentation</div></a>
|
||||
<a href="../../index.html"><div class="brand">osxphotos 0.62.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.60.5 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.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,6 +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="../../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>
|
||||
|
||||
@ -309,6 +310,10 @@
|
||||
<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"> shared_library: search for photos that are part of a shared iCloud library</span>
|
||||
<span class="sd"> not_shared_library: search for photos that are not part of a shared iCloud library</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>
|
||||
@ -397,6 +402,10 @@
|
||||
<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="n">shared_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_shared_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="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>
|
||||
@ -468,7 +477,10 @@
|
||||
<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="s2">"shared_library"</span><span class="p">,</span> <span class="s2">"not_shared_library"</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>
|
||||
|
||||
@ -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.60.5 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.60.5 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.60.5 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">
|
||||
|
||||
@ -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.58.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.58.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.58.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">
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
@ -162,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:
|
||||
|
||||
@ -361,7 +361,7 @@ Template Substitutions
|
||||
* - {tab}
|
||||
- :A tab: '\t'
|
||||
* - {osxphotos_version}
|
||||
- The osxphotos version, e.g. '0.60.7'
|
||||
- The osxphotos version, e.g. '0.62.1'
|
||||
* - {osxphotos_cmd_line}
|
||||
- The full command line used to run osxphotos
|
||||
* - {album}
|
||||
|
||||
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.60.7',
|
||||
VERSION: '0.62.1',
|
||||
LANGUAGE: 'en',
|
||||
COLLAPSE_INDEX: false,
|
||||
BUILDER: 'html',
|
||||
|
||||
229
docs/cli.html
229
docs/cli.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 Template System" href="template_help.html" /><link rel="prev" title="OSXPhotos Tutorial" href="tutorial.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>OSXPhotos Command Line Interface (CLI) - osxphotos 0.60.7 documentation</title>
|
||||
<title>OSXPhotos Command Line Interface (CLI) - osxphotos 0.62.1 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.60.7 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.62.1 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.60.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.1 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,6 +161,7 @@
|
||||
<li class="toctree-l1 current current-page"><a class="current reference internal" href="#">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="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>
|
||||
|
||||
@ -740,6 +741,30 @@ See <cite>osxphotos help timewarp</cite> for more information.</p>
|
||||
<dd><p>Search for syndicated photos that have not saved to the library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-add-locations-shared-moment">
|
||||
<span class="sig-name descname"><span class="pre">--shared-moment</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-add-locations-shared-moment" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are part of a shared moment</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-add-locations-not-shared-moment">
|
||||
<span class="sig-name descname"><span class="pre">--not-shared-moment</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-add-locations-not-shared-moment" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are not part of a shared moment</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-add-locations-shared-library">
|
||||
<span class="sig-name descname"><span class="pre">--shared-library</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-add-locations-shared-library" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are part of a shared library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-add-locations-not-shared-library">
|
||||
<span class="sig-name descname"><span class="pre">--not-shared-library</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-add-locations-not-shared-library" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are not part of a shared library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-add-locations-regex">
|
||||
<span class="sig-name descname"><span class="pre">--regex</span></span><span class="sig-prename descclassname"> <span class="pre"><REGEX</span> <span class="pre">TEMPLATE></span></span><a class="headerlink" href="#cmdoption-osxphotos-add-locations-regex" title="Permalink to this definition">#</a></dt>
|
||||
@ -1695,6 +1720,30 @@ to modify this behavior.</p>
|
||||
<dd><p>Search for syndicated photos that have not saved to the library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-shared-moment">
|
||||
<span class="sig-name descname"><span class="pre">--shared-moment</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-export-shared-moment" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are part of a shared moment</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-not-shared-moment">
|
||||
<span class="sig-name descname"><span class="pre">--not-shared-moment</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-export-not-shared-moment" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are not part of a shared moment</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-shared-library">
|
||||
<span class="sig-name descname"><span class="pre">--shared-library</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-export-shared-library" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are part of a shared library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-not-shared-library">
|
||||
<span class="sig-name descname"><span class="pre">--not-shared-library</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-export-not-shared-library" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are not part of a shared library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-regex">
|
||||
<span class="sig-name descname"><span class="pre">--regex</span></span><span class="sig-prename descclassname"> <span class="pre"><REGEX</span> <span class="pre">TEMPLATE></span></span><a class="headerlink" href="#cmdoption-osxphotos-export-regex" title="Permalink to this definition">#</a></dt>
|
||||
@ -1918,6 +1967,12 @@ to modify this behavior.</p>
|
||||
<dd><p>Drop the photo’s extension when naming sidecar files. By default, sidecar files are named in format ‘photo_filename.photo_ext.sidecar_ext’, e.g. ‘IMG_1234.JPG.xmp’. Use ‘–sidecar-drop-ext’ to ignore the photo extension. Resulting sidecar files will have name in format ‘IMG_1234.xmp’. Warning: this may result in sidecar filename collisions if there are files of different types but the same name in the output directory, e.g. ‘IMG_1234.JPG’ and ‘IMG_1234.MOV’.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-sidecar-template">
|
||||
<span class="sig-name descname"><span class="pre">--sidecar-template</span></span><span class="sig-prename descclassname"> <span class="pre"><MAKO_TEMPLATE_FILE</span> <span class="pre">SIDECAR_FILENAME_TEMPLATE</span> <span class="pre">OPTIONS></span></span><a class="headerlink" href="#cmdoption-osxphotos-export-sidecar-template" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>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 <a class="reference external" href="https://www.makotemplates.org/">https://www.makotemplates.org/</a>). 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 <cite>{filepath}</cite> 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: <cite>–sidecar-template sidecar.mako ‘{filepath}.xmp’ write_skipped,strip_lines</cite>. To do the same but to drop the photo extension from the sidecar filename: <cite>–sidecar-template sidecar.mako ‘{filepath.parent}/{filepath.stem}.xmp’ write_skipped,strip_lines</cite>. If you are not passing any options, you must pass ‘none’ as the last argument to –sidecar-template: <cite>–sidecar-template sidecar.mako ‘{filepath}.xmp’ none</cite>. For an example Mako file see <a class="reference external" href="https://raw.githubusercontent.com/RhetTbull/osxphotos/main/examples/custom_sidecar.mako">https://raw.githubusercontent.com/RhetTbull/osxphotos/main/examples/custom_sidecar.mako</a></p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-exiftool">
|
||||
<span class="sig-name descname"><span class="pre">--exiftool</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-export-exiftool" title="Permalink to this definition">#</a></dt>
|
||||
@ -2076,13 +2131,13 @@ to modify this behavior.</p>
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-cleanup">
|
||||
<span class="sig-name descname"><span class="pre">--cleanup</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-export-cleanup" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Cleanup export directory by deleting any files which were not included in this export set. For example, photos which had previously been exported and were subsequently deleted in Photos. WARNING: –cleanup will delete <em>any</em> files in the export directory that were not exported by osxphotos, for example, your own scripts or other files. Be sure this is what you intend before using –cleanup. Use –dry-run with –cleanup first if you’re not certain.</p>
|
||||
<dd><p>Cleanup export directory by deleting any files which were not included in this export set. For example, photos which had previously been exported and were subsequently deleted in Photos. WARNING: –cleanup will delete <em>any</em> files in the export directory that were not exported by osxphotos, for example, your own scripts or other files. Be sure this is what you intend before using –cleanup. Use –dry-run with –cleanup first if you’re not certain. To prevent files not generated by osxphotos from being deleted, you may specify one or more rulesin a file named <cite>.osxphotos_keep</cite> 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 <cite>#</cite> will be ignored. Reference <a class="reference external" href="https://git-scm.com/docs/gitignore#_pattern_format">https://git-scm.com/docs/gitignore#_pattern_format</a> 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 <cite>/Volumes/Photos</cite> and you want to keep all <cite>.txt</cite> files, in the top level of the export directory, you can specify <cite>/*.txt”</cite> in the .osxphotos_keep file. If you want to keep all <cite>.txt</cite> files in the export directory and all subdirectories, you can specify <cite>**/*.txt</cite>. 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.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-keep">
|
||||
<span class="sig-name descname"><span class="pre">--keep</span></span><span class="sig-prename descclassname"> <span class="pre"><KEEP_PATH></span></span><a class="headerlink" href="#cmdoption-osxphotos-export-keep" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>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/<em>.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 example if export destination is `/Volumes/Photos` and you want to keep all `.txt` files, you can specify `–keep “/Volumes/Photos/</em>.txt”` or <cite>–keep “*.txt”</cite>. If wild card is used, KEEP_PATH must be enclosed in quotes to prevent the shell from expanding the wildcard, e.g. <cite>–keep “/Volumes/Photos/*.txt”</cite>. 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.</p>
|
||||
<span class="sig-name descname"><span class="pre">--keep</span></span><span class="sig-prename descclassname"> <span class="pre"><KEEP_RULE></span></span><a class="headerlink" href="#cmdoption-osxphotos-export-keep" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>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 <a class="reference external" href="https://git-scm.com/docs/gitignore#_pattern_format">https://git-scm.com/docs/gitignore#_pattern_format</a> 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 <cite>/Volumes/Photos</cite> and you want to keep all <cite>.txt</cite> files, in the top level of the export directory, you can specify <cite>–keep “/*.txt”</cite>. If you want to keep all <cite>.txt</cite> files in the export directory and all subdirectories, you can specify <cite>–keep “**/*.txt”</cite>. 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 <cite>.osxphotos_keep</cite> 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 <cite>#</cite> will be ignored.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
@ -2106,7 +2161,18 @@ to modify this behavior.</p>
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-post-command">
|
||||
<span class="sig-name descname"><span class="pre">--post-command</span></span><span class="sig-prename descclassname"> <span class="pre"><CATEGORY</span> <span class="pre">COMMAND></span></span><a class="headerlink" href="#cmdoption-osxphotos-export-post-command" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Run COMMAND on exported files of category CATEGORY. CATEGORY can be one of: exported, new, updated, skipped, missing, exif_updated, touched, converted_to_jpeg, sidecar_json_written, sidecar_json_skipped, sidecar_exiftool_written, sidecar_exiftool_skipped, sidecar_xmp_written, sidecar_xmp_skipped, error. COMMAND is an osxphotos template string, for example: ‘–post-command exported “echo {filepath|shell_quote} >> {export_dir}/exported.txt”’, which appends the 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.</p>
|
||||
<dd><p>Run COMMAND on exported files of category CATEGORY. CATEGORY can be one of: exported, new, updated, skipped, missing, exif_updated, touched, converted_to_jpeg, sidecar_json_written, sidecar_json_skipped, sidecar_exiftool_written, sidecar_exiftool_skipped, sidecar_xmp_written, sidecar_xmp_skipped, error. COMMAND is an osxphotos template string, for example: ‘–post-command exported “echo {filepath|shell_quote} >> {export_dir}/exported.txt”’, which appends the 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 also –post-command-error and –post-function.See Post Command below.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-export-post-command-error">
|
||||
<span class="sig-name descname"><span class="pre">--post-command-error</span></span><span class="sig-prename descclassname"> <span class="pre"><ACTION></span></span><a class="headerlink" href="#cmdoption-osxphotos-export-post-command-error" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Specify either <cite>continue</cite> or <cite>break</cite> for ACTION to control behavior when a post-command fails. If <cite>continue</cite>, osxphotos will log the error and continue processing. If <cite>break</cite>, 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.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Options<span class="colon">:</span></dt>
|
||||
<dd class="field-odd"><p>continue | break</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
@ -3301,6 +3367,30 @@ If the same query option is provided multiple times, they are treated as
|
||||
<dd><p>Search for syndicated photos that have not saved to the library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-query-shared-moment">
|
||||
<span class="sig-name descname"><span class="pre">--shared-moment</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-query-shared-moment" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are part of a shared moment</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-query-not-shared-moment">
|
||||
<span class="sig-name descname"><span class="pre">--not-shared-moment</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-query-not-shared-moment" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are not part of a shared moment</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-query-shared-library">
|
||||
<span class="sig-name descname"><span class="pre">--shared-library</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-query-shared-library" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are part of a shared library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-query-not-shared-library">
|
||||
<span class="sig-name descname"><span class="pre">--not-shared-library</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-query-not-shared-library" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are not part of a shared library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-query-regex">
|
||||
<span class="sig-name descname"><span class="pre">--regex</span></span><span class="sig-prename descclassname"> <span class="pre"><REGEX</span> <span class="pre">TEMPLATE></span></span><a class="headerlink" href="#cmdoption-osxphotos-query-regex" title="Permalink to this definition">#</a></dt>
|
||||
@ -3862,6 +3952,30 @@ If the same query option is provided multiple times, they are treated as
|
||||
<dd><p>Search for syndicated photos that have not saved to the library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-repl-shared-moment">
|
||||
<span class="sig-name descname"><span class="pre">--shared-moment</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-repl-shared-moment" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are part of a shared moment</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-repl-not-shared-moment">
|
||||
<span class="sig-name descname"><span class="pre">--not-shared-moment</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-repl-not-shared-moment" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are not part of a shared moment</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-repl-shared-library">
|
||||
<span class="sig-name descname"><span class="pre">--shared-library</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-repl-shared-library" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are part of a shared library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-repl-not-shared-library">
|
||||
<span class="sig-name descname"><span class="pre">--not-shared-library</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-repl-not-shared-library" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are not part of a shared library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-repl-regex">
|
||||
<span class="sig-name descname"><span class="pre">--regex</span></span><span class="sig-prename descclassname"> <span class="pre"><REGEX</span> <span class="pre">TEMPLATE></span></span><a class="headerlink" href="#cmdoption-osxphotos-repl-regex" title="Permalink to this definition">#</a></dt>
|
||||
@ -4545,6 +4659,30 @@ two different computers, you can export the metadata to a shared folder.</p>
|
||||
<dd><p>Search for syndicated photos that have not saved to the library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-sync-shared-moment">
|
||||
<span class="sig-name descname"><span class="pre">--shared-moment</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-sync-shared-moment" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are part of a shared moment</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-sync-not-shared-moment">
|
||||
<span class="sig-name descname"><span class="pre">--not-shared-moment</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-sync-not-shared-moment" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are not part of a shared moment</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-sync-shared-library">
|
||||
<span class="sig-name descname"><span class="pre">--shared-library</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-sync-shared-library" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are part of a shared library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-sync-not-shared-library">
|
||||
<span class="sig-name descname"><span class="pre">--not-shared-library</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-sync-not-shared-library" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Search for photos that are not part of a shared library</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-sync-regex">
|
||||
<span class="sig-name descname"><span class="pre">--regex</span></span><span class="sig-prename descclassname"> <span class="pre"><REGEX</span> <span class="pre">TEMPLATE></span></span><a class="headerlink" href="#cmdoption-osxphotos-sync-regex" title="Permalink to this definition">#</a></dt>
|
||||
@ -4871,51 +5009,46 @@ See Timewarp Overview below for additional information.</p>
|
||||
</section>
|
||||
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>Usage: python -m 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...
|
||||
exiftool Run exiftool on previously exported files to update...
|
||||
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...
|
||||
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...
|
||||
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.
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="#" /><link rel="search" title="Search" href="search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Index - osxphotos 0.60.7 documentation</title>
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Index - osxphotos 0.62.1 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.60.7 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.62.1 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.60.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.1 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,6 +159,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="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>
|
||||
|
||||
@ -1601,8 +1602,6 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-not-favorite">osxphotos-sync command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li>
|
||||
--not-hdr
|
||||
|
||||
@ -1648,6 +1647,8 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-not-in-album">osxphotos-sync command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li>
|
||||
--not-incloud
|
||||
|
||||
@ -1794,6 +1795,36 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-not-shared">osxphotos-query command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-not-shared">osxphotos-repl command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
--not-shared-library
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-not-shared-library">osxphotos-add-locations command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-not-shared-library">osxphotos-export command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-not-shared-library">osxphotos-query command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-not-shared-library">osxphotos-repl command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-not-shared-library">osxphotos-sync command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
--not-shared-moment
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-not-shared-moment">osxphotos-add-locations command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-not-shared-moment">osxphotos-export command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-not-shared-moment">osxphotos-query command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-not-shared-moment">osxphotos-repl command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-not-shared-moment">osxphotos-sync command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
@ -1982,6 +2013,13 @@
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-post-command">osxphotos-export command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
--post-command-error
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-post-command-error">osxphotos-export command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
@ -2250,6 +2288,36 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-shared">osxphotos-query command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-shared">osxphotos-repl command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
--shared-library
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-shared-library">osxphotos-add-locations command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-shared-library">osxphotos-export command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-shared-library">osxphotos-query command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-shared-library">osxphotos-repl command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-shared-library">osxphotos-sync command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
--shared-moment
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-shared-moment">osxphotos-add-locations command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-shared-moment">osxphotos-export command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-shared-moment">osxphotos-query command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-shared-moment">osxphotos-repl command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-shared-moment">osxphotos-sync command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
@ -2264,6 +2332,13 @@
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-sidecar-drop-ext">osxphotos-export command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
--sidecar-template
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-sidecar-template">osxphotos-export command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
@ -3764,10 +3839,10 @@
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.QueryOptions.not_favorite">not_favorite (osxphotos.QueryOptions attribute)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="reference.html#osxphotos.QueryOptions.not_hdr">not_hdr (osxphotos.QueryOptions attribute)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="reference.html#osxphotos.QueryOptions.not_hidden">not_hidden (osxphotos.QueryOptions attribute)</a>
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.QueryOptions.not_in_album">not_in_album (osxphotos.QueryOptions attribute)</a>
|
||||
@ -3791,6 +3866,10 @@
|
||||
<li><a href="reference.html#osxphotos.QueryOptions.not_selfie">not_selfie (osxphotos.QueryOptions attribute)</a>
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.QueryOptions.not_shared">not_shared (osxphotos.QueryOptions attribute)</a>
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.QueryOptions.not_shared_library">not_shared_library (osxphotos.QueryOptions attribute)</a>
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.QueryOptions.not_shared_moment">not_shared_moment (osxphotos.QueryOptions attribute)</a>
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.QueryOptions.not_slow_mo">not_slow_mo (osxphotos.QueryOptions attribute)</a>
|
||||
</li>
|
||||
@ -3951,6 +4030,10 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-not-selfie">--not-selfie</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-not-shared">--not-shared</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-not-shared-library">--not-shared-library</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-not-shared-moment">--not-shared-moment</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-not-slow-mo">--not-slow-mo</a>
|
||||
</li>
|
||||
@ -3985,6 +4068,10 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-selfie">--selfie</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-shared">--shared</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-shared-library">--shared-library</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-shared-moment">--shared-moment</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-add-locations-slow-mo">--slow-mo</a>
|
||||
</li>
|
||||
@ -4365,6 +4452,10 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-not-selfie">--not-selfie</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-not-shared">--not-shared</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-not-shared-library">--not-shared-library</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-not-shared-moment">--not-shared-moment</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-not-slow-mo">--not-slow-mo</a>
|
||||
</li>
|
||||
@ -4393,6 +4484,8 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-portrait">--portrait</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-post-command">--post-command</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-post-command-error">--post-command-error</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-post-function">--post-function</a>
|
||||
</li>
|
||||
@ -4429,10 +4522,16 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-selfie">--selfie</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-shared">--shared</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-shared-library">--shared-library</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-shared-moment">--shared-moment</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-sidecar">--sidecar</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-sidecar-drop-ext">--sidecar-drop-ext</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-sidecar-template">--sidecar-template</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-skip-bursts">--skip-bursts</a>
|
||||
</li>
|
||||
@ -4912,6 +5011,10 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-not-selfie">--not-selfie</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-not-shared">--not-shared</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-not-shared-library">--not-shared-library</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-not-shared-moment">--not-shared-moment</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-not-slow-mo">--not-slow-mo</a>
|
||||
</li>
|
||||
@ -4950,6 +5053,10 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-selfie">--selfie</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-shared">--shared</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-shared-library">--shared-library</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-shared-moment">--shared-moment</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-slow-mo">--slow-mo</a>
|
||||
</li>
|
||||
@ -5103,6 +5210,10 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-not-selfie">--not-selfie</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-not-shared">--not-shared</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-not-shared-library">--not-shared-library</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-not-shared-moment">--not-shared-moment</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-not-slow-mo">--not-slow-mo</a>
|
||||
</li>
|
||||
@ -5137,6 +5248,10 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-selfie">--selfie</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-shared">--shared</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-shared-library">--shared-library</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-shared-moment">--shared-moment</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-slow-mo">--slow-mo</a>
|
||||
</li>
|
||||
@ -5321,6 +5436,10 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-not-screenshot">--not-screenshot</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-not-selfie">--not-selfie</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-not-shared-library">--not-shared-library</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-not-shared-moment">--not-shared-moment</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-not-slow-mo">--not-slow-mo</a>
|
||||
</li>
|
||||
@ -5357,6 +5476,10 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-selfie">--selfie</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-s">--set</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-shared-library">--shared-library</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-shared-moment">--shared-moment</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-sync-slow-mo">--slow-mo</a>
|
||||
</li>
|
||||
@ -5813,15 +5936,33 @@
|
||||
<li><a href="reference.html#osxphotos.ExportDB.set_photoinfo_for_uuid">set_photoinfo_for_uuid() (osxphotos.ExportDB method)</a>
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.ExifTool.setvalue">setvalue() (osxphotos.ExifTool method)</a>
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.PhotoInfo.share_info">share_info (osxphotos.PhotoInfo property)</a>
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.PhotoInfo.share_participants">share_participants (osxphotos.PhotoInfo property)</a>
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.PhotoInfo.shared">shared (osxphotos.PhotoInfo property)</a>
|
||||
|
||||
<ul>
|
||||
<li><a href="reference.html#osxphotos.QueryOptions.shared">(osxphotos.QueryOptions attribute)</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li><a href="reference.html#osxphotos.PhotoInfo.shared_library">shared_library (osxphotos.PhotoInfo property)</a>
|
||||
|
||||
<ul>
|
||||
<li><a href="reference.html#osxphotos.QueryOptions.shared_library">(osxphotos.QueryOptions attribute)</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="reference.html#osxphotos.PhotoInfo.shared_moment">shared_moment (osxphotos.PhotoInfo property)</a>
|
||||
|
||||
<ul>
|
||||
<li><a href="reference.html#osxphotos.QueryOptions.shared_moment">(osxphotos.QueryOptions attribute)</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li><a href="reference.html#osxphotos.PhotoInfo.shared_moment_info">shared_moment_info (osxphotos.PhotoInfo property)</a>
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.ExportOptions.sidecar">sidecar (osxphotos.ExportOptions attribute)</a>
|
||||
</li>
|
||||
<li><a href="reference.html#osxphotos.ExportOptions.sidecar_drop_ext">sidecar_drop_ext (osxphotos.ExportOptions attribute)</a>
|
||||
|
||||
316
docs/index.html
316
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.60.7 documentation</title>
|
||||
<title>osxphotos 0.62.1 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.60.7 documentation</div></a>
|
||||
<a href="#"><div class="brand">osxphotos 0.62.1 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.60.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.1 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,6 +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="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>
|
||||
|
||||
@ -282,6 +283,306 @@
|
||||
<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="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#a-name-photosdb-photosdb-a"><span class="raw-html-m2r"><a name="photosdb">PhotosDB</a></span></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-photosdb-query-query-options-queryoptions-list-photoinfo-a"><span class="raw-html-m2r"><A name="photosdb_query"></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#a-name-photosdb-keywords-keywords-a"><span class="raw-html-m2r"><a name="photosdb_keywords">`keywords`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-photosdb-albuminfo-album-info-a"><span class="raw-html-m2r"><a name="photosdb_albuminfo">`album_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-photosdb-albums-albums-a"><span class="raw-html-m2r"><a name="photosdb_albums">`albums`</a></span></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#a-name-photosdb-import-info-import-info-a"><span class="raw-html-m2r"><a name = "photosdb_import_info">`import_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-photosdb-project-info-project-info-a"><span class="raw-html-m2r"><a name="photosdb_project_info">`project_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-photosdb-moment-info-moment-info-a"><span class="raw-html-m2r"><a name="photosdb_moment_info">`moment_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-photosdb-folder-info-folder-info-a"><span class="raw-html-m2r"><a name="photosdb_folder_info">`folder_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-photosdb-folders-folders-a"><span class="raw-html-m2r"><a name="photosdb_folders">`folders`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-photosdb-persons-persons-a"><span class="raw-html-m2r"><a name="photosdb_persons">`persons`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-photosdb-person-info-person-info-a"><span class="raw-html-m2r"><a name="photosdb_person_info">`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#a-name-photosdb-labels-labels-a"><span class="raw-html-m2r"><a name="photosdb_labels">`labels`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-photosdb-labels-normalized-labels-normalized-a"><span class="raw-html-m2r"><a name="photosdb_labels_normalized">`labels_normalized`</a></span></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#id19"><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#id21">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#a-name-photoinfo-photoinfo-a"><span class="raw-html-m2r"><a name="photoinfo">PhotoInfo</a></span></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#id22"><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#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#id24"><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#id26"><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#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#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-photoinfo-personinfo-person-info-a"><span class="raw-html-m2r"><a name="photoinfo_personinfo">`person_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-photooinfo-faceinfo-face-info-a"><span class="raw-html-m2r"><a name="photooinfo_faceinfo">`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#id38"><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#id40"><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#id42"><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#id44"><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#id46"><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#id48"><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#id50"><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#id61"><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>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#shared-moment"><code class="docutils literal notranslate"><span class="pre">shared_moment</span></code></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#shared-library"><code class="docutils literal notranslate"><span class="pre">shared_library</span></code></a></li>
|
||||
<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#id64"><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#id65"><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#id67"><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#id70"><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#id74"><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#id78"><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#id80"><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-photoinfo-searchinfo-search-info-a"><span class="raw-html-m2r"><a name="photoinfo_searchinfo">`search_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-photoinfo-search-info-normalized-search-info-normalized-a"><span class="raw-html-m2r"><a name="photoinfo_search_info_normalized">`search_info_normalized`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-photoinfo-exif-info-exif-info-a"><span class="raw-html-m2r"><a name="photoinfo_exif_info">`exif_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-photoinfo-exiftool-exiftool-a"><span class="raw-html-m2r"><a name="photoinfo_exiftool">`exiftool`</a></span></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-photoinfo-detected-text-detected-text-confidence-threshold-text-detection-confidence-threshold-a"><span class="raw-html-m2r"><a name="photoinfo_detected_text">`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#id94">ExifInfo</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="API_README.html#id95">AlbumInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#id96"><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#id97"><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#id101"><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#id104"><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#id105">ImportInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#id106"><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#id108"><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#id109"><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#id110"><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#id111"><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#id112">ProjectInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#id113"><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#id114"><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#id116"><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#id117"><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#id118">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#id119"><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#id120"><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#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">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#id124"><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#id125"><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#id126">FolderInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#id127"><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#id128"><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-folderinfo-album-info-album-info-a"><span class="raw-html-m2r"><a name="folderinfo_album_info">`album_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-folderinfo-album-info-shared-album-info-shared-a"><span class="raw-html-m2r"><a name="folderinfo_album_info_shared">`album_info_shared`</a></span></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#id132"><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#id134"><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#id135">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#id136">ScoreInfo</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="API_README.html#id137">SearchInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#id138"><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#id139"><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#id140">PersonInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#id141"><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#id142"><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#id144"><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#id145"><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#id146">FaceInfo</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-faceinfo-uuid-uuid-a"><span class="raw-html-m2r"><a name="faceinfo_uuid">`uuid`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-faceinfo-name-name-a"><span class="raw-html-m2r"><a name="faceinfo_name">`name`</a></span></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#a-name-faceinfo-person-info-person-info-a"><span class="raw-html-m2r"><a name="faceinfo_person_info">`person_info`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-faceinfo-photo-photo-a"><span class="raw-html-m2r"><a name="faceinfo_photo">`photo`</a></span></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#a-name-faceinfo-asdict-asdict-a"><span class="raw-html-m2r"><a name="faceinfo_asdict">`asdict()`</a></span></a></li>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#a-name-faceinfo-json-json-a"><span class="raw-html-m2r"><a name="faceinfo_json">`json()`</a></span></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="API_README.html#id149">CommentInfo</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="API_README.html#id150">LikeInfo</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="API_README.html#id151">AdjustmentsInfo</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="API_README.html#id152">PhotoTables</a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="API_README.html#id153">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#id162">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#id165">Utility Functions</a><ul>
|
||||
<li class="toctree-l4"><a class="reference internal" href="API_README.html#id166"><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#id167"><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#id168">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>
|
||||
@ -541,7 +842,12 @@
|
||||
<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.share_info"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.share_info</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.PhotoInfo.share_participants"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.share_participants</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_library"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.shared_library</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.shared_moment_info"><code class="docutils literal notranslate"><span class="pre">PhotoInfo.shared_moment_info</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>
|
||||
@ -710,6 +1016,10 @@
|
||||
<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>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.shared_library"><code class="docutils literal notranslate"><span class="pre">QueryOptions.shared_library</span></code></a></li>
|
||||
<li class="toctree-l3"><a class="reference internal" href="reference.html#osxphotos.QueryOptions.not_shared_library"><code class="docutils literal notranslate"><span class="pre">QueryOptions.not_shared_library</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>
|
||||
|
||||
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.60.7 documentation</title>
|
||||
<title>OSXPhotos - osxphotos 0.62.1 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.60.7 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.62.1 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.60.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.1 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,6 +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="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>
|
||||
|
||||
|
||||
@ -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 Reference" 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 API" href="API_README.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.60.7 documentation</title>
|
||||
<title>OSXPhotos Python Package Overview - osxphotos 0.62.1 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.60.7 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.62.1 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.60.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.1 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,6 +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="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>
|
||||
|
||||
@ -387,12 +388,12 @@ as well as <code class="docutils literal notranslate"><span class="pre">{functio
|
||||
<footer>
|
||||
|
||||
<div class="related-pages">
|
||||
<a class="next-page" href="reference.html">
|
||||
<a class="next-page" href="API_README.html">
|
||||
<div class="page-info">
|
||||
<div class="context">
|
||||
<span>Next</span>
|
||||
</div>
|
||||
<div class="title">OSXPhotos Python Reference</div>
|
||||
<div class="title">OSXPhotos Python API</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.60.7 documentation</title>
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Python Module Index - osxphotos 0.62.1 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.60.7 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.62.1 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.60.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.1 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,6 +159,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="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>
|
||||
|
||||
|
||||
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.60.7 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.62.1 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.60.7 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.62.1 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.60.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.1 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,6 +158,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="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>
|
||||
|
||||
|
||||
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.60.7 documentation</title>
|
||||
<title>OSXPhotos Template System - osxphotos 0.62.1 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.60.7 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.62.1 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.60.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.1 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,6 +161,7 @@
|
||||
<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="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>
|
||||
|
||||
@ -320,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">
|
||||
@ -613,7 +614,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{osxphotos_version}</p></td>
|
||||
<td><p>The osxphotos version, e.g. ‘0.60.7’</p></td>
|
||||
<td><p>The osxphotos version, e.g. ‘0.62.1’</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{osxphotos_cmd_line}</p></td>
|
||||
<td><p>The full command line used to run osxphotos</p></td>
|
||||
|
||||
@ -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.60.7 documentation</title>
|
||||
<title>OSXPhotos Tutorial - osxphotos 0.62.1 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.60.7 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.62.1 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.60.7 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.62.1 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,6 +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="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>
|
||||
|
||||
|
||||
3287
docsrc/source/api_readme.rst
Normal file
3287
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
|
||||
|
||||
|
||||
|
||||
@ -162,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:
|
||||
|
||||
@ -361,7 +361,7 @@ Template Substitutions
|
||||
* - {tab}
|
||||
- :A tab: '\t'
|
||||
* - {osxphotos_version}
|
||||
- The osxphotos version, e.g. '0.60.7'
|
||||
- The osxphotos version, e.g. '0.62.1'
|
||||
* - {osxphotos_cmd_line}
|
||||
- The full command line used to run osxphotos
|
||||
* - {album}
|
||||
|
||||
107
examples/add_size_to_caption.py
Normal file
107
examples/add_size_to_caption.py
Normal file
@ -0,0 +1,107 @@
|
||||
"""Add the photo size in form widthxheight to each photo's caption/description in Photos
|
||||
|
||||
Run this with `osxphotos run add_size_to_caption.py`
|
||||
|
||||
Run `osxphotos run add_size_to_caption.py --help` for help.
|
||||
|
||||
Intended to be run with osxphotos; see https://github.com/RhetTbull/osxphotos
|
||||
|
||||
This may be helpful for allowing Smart Albums in Photos to filter by photo size.
|
||||
Reference this reddit post: https://www.reddit.com/r/ApplePhotos/comments/15r4fk6/smart_album_filter_for_photovideo_dimensions/
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import click
|
||||
import photoscript
|
||||
|
||||
import osxphotos
|
||||
from osxphotos.cli import echo, echo_error, query_command, verbose
|
||||
from osxphotos.utils import pluralize
|
||||
|
||||
|
||||
@query_command
|
||||
@click.option(
|
||||
"--original",
|
||||
is_flag=True,
|
||||
help="If photo is edited, use original image size instead of edited image size",
|
||||
)
|
||||
@click.option(
|
||||
"--clear",
|
||||
is_flag=True,
|
||||
help="Remove existing size information from description",
|
||||
)
|
||||
def main(photos: list[osxphotos.PhotoInfo], original: bool, clear: bool, **kwargs):
|
||||
"""Add the photo size in form widthxheight to each photo's caption in Photos
|
||||
If a photo has a caption, the size will be appended to the caption.
|
||||
|
||||
Use --original to use the original image size instead of the edited image size.
|
||||
Use --clear to remove existing size information from caption.
|
||||
"""
|
||||
|
||||
# filter out any shared photos
|
||||
photos = [p for p in photos if not p.shared]
|
||||
|
||||
echo(f"Processing {len(photos)} {pluralize(len(photos), 'photo', 'photos')}...")
|
||||
if clear:
|
||||
clear_size_str_from_photos(photos, original)
|
||||
else:
|
||||
add_size_str_to_photos(photos, original)
|
||||
echo("Done.")
|
||||
|
||||
|
||||
def compute_size_str(photo: osxphotos.PhotoInfo, original: bool) -> str:
|
||||
"""Return the size string for a given photo"""
|
||||
return (
|
||||
f"{photo.original_width}x{photo.original_height}"
|
||||
if original
|
||||
else f"{photo.width}x{photo.height}"
|
||||
)
|
||||
|
||||
|
||||
def add_size_str_to_photos(photos: list[osxphotos.PhotoInfo], original: bool):
|
||||
"""Add size string to photo description/caption"""
|
||||
for photo in photos:
|
||||
size_str = compute_size_str(photo, original)
|
||||
description = photo.description or "" # description can be None
|
||||
if size_str in description:
|
||||
verbose(
|
||||
f"Skipping {photo.original_filename} ({photo.uuid}) ({size_str} already in caption)"
|
||||
)
|
||||
continue
|
||||
new_desc = f"{photo.description}\n{size_str}" if description else size_str
|
||||
verbose(
|
||||
f"Updating caption for {photo.original_filename} ({photo.uuid}) to {new_desc}"
|
||||
)
|
||||
update_description(photo, new_desc)
|
||||
|
||||
|
||||
def clear_size_str_from_photos(photos: list[osxphotos.PhotoInfo], original: bool):
|
||||
"""Clear size string from photo description/caption"""
|
||||
for photo in photos:
|
||||
size_str = compute_size_str(photo, original)
|
||||
description = photo.description or "" # description can be None
|
||||
if size_str not in description:
|
||||
verbose(
|
||||
f"Skipping {photo.original_filename} ({photo.uuid}) ({size_str} not in caption)"
|
||||
)
|
||||
continue
|
||||
new_desc = description.replace(size_str, "").strip()
|
||||
verbose(
|
||||
f"Setting caption for {photo.original_filename} ({photo.uuid}) to {new_desc}"
|
||||
)
|
||||
update_description(photo, new_desc)
|
||||
|
||||
|
||||
def update_description(photo: osxphotos.PhotoInfo, new_desc: str):
|
||||
"""Update photo caption"""
|
||||
try:
|
||||
photoscript.Photo(photo.uuid).description = new_desc
|
||||
except Exception as e:
|
||||
echo_error(
|
||||
f"Error updating caption for {photo.original_filename} ({photo.uuid}): {e}"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
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,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
|
||||
|
||||
@ -23,15 +23,18 @@ TIME_DELTA = (datetime(2001, 1, 1, 0, 0) - datetime(1970, 1, 1, 0, 0)).total_sec
|
||||
# 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"
|
||||
|
||||
@ -39,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
|
||||
@ -47,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",
|
||||
@ -61,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",
|
||||
@ -73,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",
|
||||
@ -85,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",
|
||||
@ -97,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",
|
||||
},
|
||||
}
|
||||
|
||||
@ -127,6 +159,7 @@ _TESTED_OS_VERSIONS = [
|
||||
("13", "2"),
|
||||
("13", "3"),
|
||||
("13", "4"),
|
||||
("14", "0"),
|
||||
]
|
||||
|
||||
# Photos 5 has persons who are empty string if unidentified face
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.60.7"
|
||||
__version__ = "0.62.1"
|
||||
|
||||
@ -611,6 +611,26 @@ _QUERY_PARAMETERS_DICT = {
|
||||
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",
|
||||
|
||||
@ -93,13 +93,25 @@ def debug_dump(
|
||||
pprint.pprint(photosdb._dbpersons_fullname)
|
||||
elif attr == "photos":
|
||||
photos = photosdb.query(options=query_options)
|
||||
uuid = [photo.uuid for photo in photos]
|
||||
for uuid_ in uuid:
|
||||
print(f"_dbphotos['{uuid_}']:")
|
||||
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:
|
||||
pprint.pprint(photosdb._dbphotos[uuid_])
|
||||
print(photosdb._dbphotos[p.uuid])
|
||||
except KeyError:
|
||||
print(f"Did not find uuid {uuid_} in _dbphotos")
|
||||
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)
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
"""export command for osxphotos CLI"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import atexit
|
||||
import inspect
|
||||
import os
|
||||
@ -9,11 +11,12 @@ import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from typing import Iterable, List, Optional, Tuple
|
||||
from typing import Any, Callable, Iterable, List, Literal, Optional, Tuple
|
||||
|
||||
import click
|
||||
|
||||
import osxphotos
|
||||
import osxphotos.gitignorefile
|
||||
from osxphotos._constants import (
|
||||
_EXIF_TOOL_URL,
|
||||
_OSXPHOTOS_NONE_SENTINEL,
|
||||
@ -88,9 +91,10 @@ from .common import (
|
||||
)
|
||||
from .help import ExportCommand, get_help_msg
|
||||
from .list import _list_libraries
|
||||
from .param_types import ExportDBType, FunctionCall, TemplateString
|
||||
from .param_types import CSVOptions, ExportDBType, FunctionCall, TemplateString
|
||||
from .report_writer import ReportWriterNoOp, export_report_writer_factory
|
||||
from .rich_progress import rich_progress
|
||||
from .sidecar import generate_user_sidecar
|
||||
from .verbose import get_verbose_console, verbose_print
|
||||
|
||||
|
||||
@ -304,7 +308,8 @@ from .verbose import get_verbose_console, verbose_print
|
||||
"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 ''")
|
||||
"--filename 'IMG_{edited_version?E,}{id:04d}' --edited-suffix ''",
|
||||
)
|
||||
@click.option(
|
||||
"--sidecar",
|
||||
default=None,
|
||||
@ -338,6 +343,53 @@ from .verbose import get_verbose_console, verbose_print
|
||||
"Warning: this may result in sidecar filename collisions if there are files of different "
|
||||
"types but the same name in the output directory, e.g. 'IMG_1234.JPG' and 'IMG_1234.MOV'.",
|
||||
)
|
||||
@click.option(
|
||||
"--sidecar-template",
|
||||
metavar="MAKO_TEMPLATE_FILE SIDECAR_FILENAME_TEMPLATE OPTIONS",
|
||||
multiple=True,
|
||||
type=click.Tuple(
|
||||
[
|
||||
click.Path(dir_okay=False, file_okay=True, exists=True),
|
||||
TemplateString(),
|
||||
CSVOptions(
|
||||
[
|
||||
"write_skipped",
|
||||
"strip_whitespace",
|
||||
"strip_lines",
|
||||
"skip_zero",
|
||||
"catch_errors",
|
||||
"none",
|
||||
]
|
||||
),
|
||||
]
|
||||
),
|
||||
help="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/RhetTbull/osxphotos/main/examples/custom_sidecar.mako",
|
||||
)
|
||||
@click.option(
|
||||
"--exiftool",
|
||||
is_flag=True,
|
||||
@ -561,27 +613,43 @@ from .verbose import get_verbose_console, verbose_print
|
||||
"For example, photos which had previously been exported and were subsequently deleted in Photos. "
|
||||
"WARNING: --cleanup will delete *any* files in the export directory that were not exported by osxphotos, "
|
||||
"for example, your own scripts or other files. Be sure this is what you intend before using "
|
||||
"--cleanup. Use --dry-run with --cleanup first if you're not certain.",
|
||||
"--cleanup. Use --dry-run with --cleanup first if you're not certain. "
|
||||
"To prevent files not generated by osxphotos from being deleted, you may specify one or more rules"
|
||||
"in 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, "
|
||||
'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.",
|
||||
)
|
||||
@click.option(
|
||||
"--keep",
|
||||
metavar="KEEP_PATH",
|
||||
metavar="KEEP_RULE",
|
||||
nargs=1,
|
||||
multiple=True,
|
||||
help="When used with --cleanup, prevents file or directory KEEP_PATH from being deleted "
|
||||
help="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_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. "
|
||||
"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, "
|
||||
'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.",
|
||||
'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. ",
|
||||
)
|
||||
@click.option(
|
||||
"--add-exported-to-album",
|
||||
@ -617,11 +685,22 @@ from .verbose import get_verbose_console, verbose_print
|
||||
"COMMAND is an osxphotos template string, for example: '--post-command exported \"echo {filepath|shell_quote} >> {export_dir}/exported.txt\"', "
|
||||
"which appends the 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 also --post-command-error and --post-function."
|
||||
"See Post Command below.",
|
||||
type=click.Tuple(
|
||||
[click.Choice(POST_COMMAND_CATEGORIES, case_sensitive=False), TemplateString()]
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--post-command-error",
|
||||
metavar="ACTION",
|
||||
help="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. ",
|
||||
type=click.Choice(["continue", "break"], case_sensitive=False),
|
||||
)
|
||||
@click.option(
|
||||
"--post-function",
|
||||
metavar="filename.py::function",
|
||||
@ -844,6 +923,7 @@ def export(
|
||||
place,
|
||||
portrait,
|
||||
post_command,
|
||||
post_command_error,
|
||||
post_function,
|
||||
preview,
|
||||
preview_if_missing,
|
||||
@ -863,6 +943,7 @@ def export(
|
||||
export_aae,
|
||||
sidecar,
|
||||
sidecar_drop_ext,
|
||||
sidecar_template,
|
||||
skip_bursts,
|
||||
skip_edited,
|
||||
skip_live,
|
||||
@ -894,6 +975,10 @@ def export(
|
||||
not_syndicated,
|
||||
saved_to_library,
|
||||
not_saved_to_library,
|
||||
shared_moment,
|
||||
not_shared_moment,
|
||||
shared_library,
|
||||
not_shared_library,
|
||||
selected=False, # Isn't provided on unsupported platforms
|
||||
# debug, # debug, watch, breakpoint handled in cli/__init__.py
|
||||
# watch,
|
||||
@ -994,6 +1079,7 @@ def export(
|
||||
exiftool_merge_persons = cfg.exiftool_merge_persons
|
||||
exiftool_option = cfg.exiftool_option
|
||||
exiftool_path = cfg.exiftool_path
|
||||
export_aae = cfg.export_aae
|
||||
export_as_hardlink = cfg.export_as_hardlink
|
||||
export_by_date = cfg.export_by_date
|
||||
exportdb = cfg.exportdb
|
||||
@ -1052,10 +1138,14 @@ def export(
|
||||
not_panorama = cfg.not_panorama
|
||||
not_portrait = cfg.not_portrait
|
||||
not_reference = cfg.not_reference
|
||||
not_saved_to_library = cfg.not_saved_to_library
|
||||
not_screenshot = cfg.not_screenshot
|
||||
not_selfie = cfg.not_selfie
|
||||
not_shared = cfg.not_shared
|
||||
not_shared_library = cfg.not_shared_library
|
||||
not_shared_moment = cfg.not_shared_moment
|
||||
not_slow_mo = cfg.not_slow_mo
|
||||
not_syndicated = cfg.not_syndicated
|
||||
not_time_lapse = cfg.not_time_lapse
|
||||
only_movies = cfg.only_movies
|
||||
only_new = cfg.only_new
|
||||
@ -1069,6 +1159,7 @@ def export(
|
||||
place = cfg.place
|
||||
portrait = cfg.portrait
|
||||
post_command = cfg.post_command
|
||||
post_command_error = cfg.post_command_error
|
||||
post_function = cfg.post_function
|
||||
preview = cfg.preview
|
||||
preview_if_missing = cfg.preview_if_missing
|
||||
@ -1081,13 +1172,16 @@ def export(
|
||||
replace_keywords = cfg.replace_keywords
|
||||
report = cfg.report
|
||||
retry = cfg.retry
|
||||
saved_to_library = cfg.saved_to_library
|
||||
screenshot = cfg.screenshot
|
||||
selected = cfg.selected
|
||||
selfie = cfg.selfie
|
||||
shared = cfg.shared
|
||||
export_aae = cfg.export_aae
|
||||
shared_library = cfg.shared_library
|
||||
shared_moment = cfg.shared_moment
|
||||
sidecar = cfg.sidecar
|
||||
sidecar_drop_ext = cfg.sidecar_drop_ext
|
||||
sidecar_template = cfg.sidecar_template
|
||||
skip_bursts = cfg.skip_bursts
|
||||
skip_edited = cfg.skip_edited
|
||||
skip_live = cfg.skip_live
|
||||
@ -1097,6 +1191,7 @@ def export(
|
||||
skip_uuid_from_file = cfg.skip_uuid_from_file
|
||||
slow_mo = cfg.slow_mo
|
||||
strip = cfg.strip
|
||||
syndicated = cfg.syndicated
|
||||
theme = cfg.theme
|
||||
time_lapse = cfg.time_lapse
|
||||
timestamp = cfg.timestamp
|
||||
@ -1112,14 +1207,11 @@ def export(
|
||||
uti = cfg.uti
|
||||
uuid = cfg.uuid
|
||||
uuid_from_file = cfg.uuid_from_file
|
||||
# this is the one option that is named differently in the config file than the variable passed by --verbose (verbose_flag)
|
||||
verbose_flag = cfg.verbose
|
||||
verbose_flag = (
|
||||
cfg.verbose
|
||||
) # this is named differently in the config file than the variable passed by --verbose (verbose_flag)
|
||||
xattr_template = cfg.xattr_template
|
||||
year = cfg.year
|
||||
syndicated = cfg.syndicated
|
||||
not_syndicated = cfg.not_syndicated
|
||||
saved_to_library = cfg.saved_to_library
|
||||
not_saved_to_library = cfg.not_saved_to_library
|
||||
|
||||
# config file might have changed verbose
|
||||
verbose = verbose_print(verbose=verbose_flag, timestamp=timestamp, theme=theme)
|
||||
@ -1171,6 +1263,7 @@ def export(
|
||||
("title", "no_title"),
|
||||
("syndicated", "not_syndicated"),
|
||||
("saved_to_library", "not_saved_to_library"),
|
||||
("shared_moment", "not_shared_moment"),
|
||||
]
|
||||
dependent_options = [
|
||||
("append", ("report")),
|
||||
@ -1468,18 +1561,30 @@ def export(
|
||||
kwargs["photo"] = p
|
||||
kwargs["photo_num"] = photo_num
|
||||
export_results = export_photo(**kwargs)
|
||||
if post_function:
|
||||
for function in post_function:
|
||||
# post function is tuple of (function, filename.py::function_name)
|
||||
verbose(f"Calling post-function [bold]{function[1]}")
|
||||
if not dry_run:
|
||||
try:
|
||||
function[0](p, export_results, verbose)
|
||||
except Exception as e:
|
||||
rich_echo_error(
|
||||
f"[error]Error running post-function [italic]{function[1]}[/italic]: {e}"
|
||||
)
|
||||
|
||||
# generate custom sidecars if needed
|
||||
if sidecar_template:
|
||||
export_results += generate_user_sidecar(
|
||||
photo=p,
|
||||
export_results=export_results,
|
||||
sidecar_template=sidecar_template,
|
||||
exiftool_path=exiftool_path,
|
||||
export_dir=dest,
|
||||
dry_run=dry_run,
|
||||
verbose=verbose,
|
||||
)
|
||||
|
||||
# run post functions
|
||||
if run_results := run_post_function(
|
||||
photo=p,
|
||||
post_function=post_function,
|
||||
export_results=export_results,
|
||||
verbose=verbose,
|
||||
dry_run=dry_run,
|
||||
):
|
||||
export_results += run_results
|
||||
|
||||
# run post command
|
||||
run_post_command(
|
||||
photo=p,
|
||||
post_command=post_command,
|
||||
@ -1487,7 +1592,7 @@ def export(
|
||||
export_dir=dest,
|
||||
dry_run=dry_run,
|
||||
exiftool_path=exiftool_path,
|
||||
export_db=export_db,
|
||||
on_error=post_command_error,
|
||||
verbose=verbose,
|
||||
)
|
||||
|
||||
@ -1649,6 +1754,7 @@ def export(
|
||||
if cleanup:
|
||||
db_file = str(pathlib.Path(export_db_path).resolve())
|
||||
db_files = [db_file, db_file + "-wal", db_file + "-shm"]
|
||||
keep_file = str(pathlib.Path(dest) / ".osxphotos_keep")
|
||||
all_files = (
|
||||
results.exported
|
||||
+ results.skipped
|
||||
@ -1662,35 +1768,46 @@ def export(
|
||||
+ results.sidecar_exiftool_skipped
|
||||
+ results.sidecar_xmp_written
|
||||
+ results.sidecar_xmp_skipped
|
||||
+ results.sidecar_user_written
|
||||
+ results.sidecar_user_skipped
|
||||
+ results.user_written
|
||||
+ results.user_skipped
|
||||
# include missing so a file that was already in export directory
|
||||
# but was missing on --update doesn't get deleted
|
||||
# (better to have old version than none)
|
||||
+ results.missing
|
||||
# include files that have error in case they exist from previous export
|
||||
+ [r[0] for r in results.error]
|
||||
# don't delete export database files
|
||||
+ db_files
|
||||
# include the .osxphotos_keep file
|
||||
+ [keep_file]
|
||||
)
|
||||
|
||||
# if --report, add report file to keep list to prevent it from being deleted
|
||||
if report:
|
||||
all_files.append(report)
|
||||
|
||||
# gather any files that should be kept from both .osxphotos_keep and --keep
|
||||
dirs_to_keep = []
|
||||
if keep:
|
||||
files_to_keep, dirs_to_keep = collect_files_to_keep(keep, dest)
|
||||
all_files += files_to_keep
|
||||
files_to_keep, dirs_to_keep = collect_files_to_keep(keep, dest)
|
||||
all_files += files_to_keep
|
||||
|
||||
rich_echo(f"Cleaning up [filepath]{dest}")
|
||||
cleaned_files, cleaned_dirs = cleanup_files(
|
||||
dest, all_files, dirs_to_keep, fileutil, verbose=verbose
|
||||
)
|
||||
file_str = "files" if len(cleaned_files) != 1 else "file"
|
||||
dir_str = "directories" if len(cleaned_dirs) != 1 else "directory"
|
||||
|
||||
rich_echo(
|
||||
f"Deleted: [num]{len(cleaned_files)}[/num] {file_str}, [num]{len(cleaned_dirs)}[/num] {dir_str}"
|
||||
)
|
||||
|
||||
report_writer.write(
|
||||
ExportResults(deleted_files=cleaned_files, deleted_directories=cleaned_dirs)
|
||||
)
|
||||
|
||||
results.deleted_files = cleaned_files
|
||||
results.deleted_directories = cleaned_dirs
|
||||
|
||||
@ -1761,7 +1878,7 @@ def export_photo(
|
||||
num_photos=1,
|
||||
tmpdir=None,
|
||||
update_errors=False,
|
||||
):
|
||||
) -> ExportResults:
|
||||
"""Helper function for export that does the actual export
|
||||
|
||||
Args:
|
||||
@ -1812,6 +1929,7 @@ def export_photo(
|
||||
use_photos_export: bool; if True forces the use of AppleScript to export even if photo not missing
|
||||
verbose: callable for verbose output
|
||||
tmpdir: optional str; temporary directory to use for export
|
||||
|
||||
Returns:
|
||||
list of path(s) of exported photo or None if photo was missing
|
||||
|
||||
@ -2184,7 +2302,7 @@ def export_photo_to_directory(
|
||||
use_photokit,
|
||||
verbose,
|
||||
tmpdir,
|
||||
):
|
||||
) -> ExportResults:
|
||||
"""Export photo to directory dest_path"""
|
||||
|
||||
results = ExportResults()
|
||||
@ -2479,22 +2597,40 @@ def collect_files_to_keep(
|
||||
"""Collect all files to keep for --keep/--cleanup.
|
||||
|
||||
Args:
|
||||
keep: Iterable of filepaths to keep; each path may be a filepath, a filepath/wildcard, or a directory path.
|
||||
keep: Iterable of patterns to keep; each pattern is a pattern that follows gitignore syntax
|
||||
export_dir: the export directory which will be used to resolve paths when paths in keep are relative instead of absolute
|
||||
|
||||
Returns:
|
||||
tuple of [files_to_keep], [dirs_to_keep]
|
||||
"""
|
||||
export_dir = pathlib.Path(export_dir)
|
||||
keepers = []
|
||||
export_dir = pathlib.Path(export_dir).expanduser()
|
||||
export_dir_str = str(export_dir)
|
||||
|
||||
KEEP_RULEs = []
|
||||
|
||||
# parse .osxphotos_keep file if it exists
|
||||
keep_file: pathlib.Path = export_dir / ".osxphotos_keep"
|
||||
if keep_file.is_file():
|
||||
for line in keep_file.read_text().splitlines():
|
||||
line = line.rstrip("\r\n")
|
||||
KEEP_RULEs.append(line)
|
||||
|
||||
# parse any patterns passed via --keep
|
||||
# do this after the file so negations to the file could be applied via --keep
|
||||
for k in keep:
|
||||
keeper = pathlib.Path(k).expanduser()
|
||||
if not keeper.is_absolute():
|
||||
# relative path: relative to export_dir
|
||||
keeper = export_dir / keeper
|
||||
if keeper.is_dir():
|
||||
keepers.extend(keeper.glob("**/*"))
|
||||
keepers.extend(keeper.parent.glob(keeper.name))
|
||||
if k.startswith(export_dir_str):
|
||||
# allow full path to be specified for keep (e.g. --keep /path/to/file)
|
||||
KEEP_RULEs.append(k.replace(export_dir_str, ""))
|
||||
else:
|
||||
KEEP_RULEs.append(k)
|
||||
|
||||
if not KEEP_RULEs:
|
||||
return [], []
|
||||
|
||||
# have some rules to apply
|
||||
matcher = osxphotos.gitignorefile.parse_pattern_list(KEEP_RULEs, export_dir)
|
||||
keepers = []
|
||||
keepers = [path for path in export_dir.rglob("*") if matcher(path)]
|
||||
files_to_keep = [str(k) for k in keepers if k.is_file()]
|
||||
dirs_to_keep = [str(k) for k in keepers if k.is_dir()]
|
||||
return files_to_keep, dirs_to_keep
|
||||
@ -2723,20 +2859,52 @@ def write_extended_attributes(
|
||||
return list(written), [f for f in skipped if f not in written]
|
||||
|
||||
|
||||
def run_post_function(
|
||||
photo: osxphotos.PhotoInfo,
|
||||
post_function: tuple[
|
||||
tuple[
|
||||
Callable[
|
||||
[osxphotos.PhotoInfo, ExportResults, Callable[[Any], None]],
|
||||
None | ExportResults,
|
||||
],
|
||||
str,
|
||||
],
|
||||
...,
|
||||
],
|
||||
export_results: ExportResults,
|
||||
verbose: Callable[[Any], None],
|
||||
dry_run: bool,
|
||||
) -> ExportResults:
|
||||
"""Run the --post-function functions"""
|
||||
returned_results = ExportResults()
|
||||
for function in post_function:
|
||||
# post function is tuple of (function, filename.py::function_name)
|
||||
verbose(f"Calling post-function [bold]{function[1]}")
|
||||
if not dry_run:
|
||||
try:
|
||||
if results := function[0](photo, export_results, verbose):
|
||||
returned_results += results
|
||||
except Exception as e:
|
||||
rich_echo_error(
|
||||
f"[error]Error running post-function [italic]{function[1]}[/italic]: {e}"
|
||||
)
|
||||
raise e
|
||||
return returned_results
|
||||
|
||||
|
||||
def run_post_command(
|
||||
photo,
|
||||
post_command,
|
||||
export_results,
|
||||
export_dir,
|
||||
dry_run,
|
||||
exiftool_path,
|
||||
export_db,
|
||||
verbose,
|
||||
photo: osxphotos.PhotoInfo,
|
||||
post_command: tuple[tuple[str, str]],
|
||||
export_results: ExportResults,
|
||||
export_dir: str | pathlib.Path,
|
||||
dry_run: bool,
|
||||
exiftool_path: str,
|
||||
on_error: Literal["break", "continue"] | None,
|
||||
verbose: Callable[[Any], None],
|
||||
):
|
||||
"""Run --post-command commands"""
|
||||
# todo: pass in RenderOptions from export? (e.g. so it contains strip, etc?)
|
||||
# todo: need a shell_quote template type:
|
||||
# {shell_quote,{filepath}/foo/bar}
|
||||
# that quotes everything in the default value
|
||||
|
||||
for category, command_template in post_command:
|
||||
files = getattr(export_results, category)
|
||||
for f in files:
|
||||
@ -2750,7 +2918,6 @@ def run_post_command(
|
||||
if command:
|
||||
verbose(f'Running command: "{command}"')
|
||||
if not dry_run:
|
||||
args = shlex.split(command)
|
||||
cwd = pathlib.Path(f).parent
|
||||
run_error = None
|
||||
run_results = None
|
||||
@ -2759,11 +2926,18 @@ def run_post_command(
|
||||
except Exception as e:
|
||||
run_error = e
|
||||
finally:
|
||||
run_error = run_error or run_results.returncode
|
||||
if run_error:
|
||||
rich_echo_error(
|
||||
f'[error]Error running command "{command}": {run_error}'
|
||||
)
|
||||
returncode = run_results.returncode if run_results else None
|
||||
if run_error or returncode:
|
||||
# there was an error running the command
|
||||
error_str = f'Error running command "{command}": return code: {returncode}, exception: {run_error}'
|
||||
rich_echo_error(f"[error]{error_str}[/]")
|
||||
if not on_error:
|
||||
# no error handling specified, raise exception
|
||||
raise RuntimeError(error_str)
|
||||
if on_error == "break":
|
||||
# break out of loop and return
|
||||
return
|
||||
# else on_error must be continue
|
||||
|
||||
|
||||
def render_and_validate_report(report: str, exiftool_path: str, export_dir: str) -> str:
|
||||
|
||||
@ -362,7 +362,7 @@ def set_photo_metadata(
|
||||
photo.title = normalize_unicode(metadata.title)
|
||||
photo.description = normalize_unicode(metadata.description)
|
||||
keywords = metadata.keywords.copy()
|
||||
keywords =normalize_unicode(keywords)
|
||||
keywords = normalize_unicode(keywords)
|
||||
if merge_keywords:
|
||||
if old_keywords := normalize_unicode(photo.keywords):
|
||||
keywords.extend(old_keywords)
|
||||
|
||||
@ -101,6 +101,22 @@ def orphans(ctx, cli_obj, export, db, verbose_flag, timestamp, theme):
|
||||
)
|
||||
scan_for_files(directory, uuids_in_library)
|
||||
|
||||
# scopes directory (Photos 7+)
|
||||
if photosdb.photos_version >= 7:
|
||||
verbose_("Scanning scopes cloudsharing files")
|
||||
directory = joinpath(
|
||||
photosdb.library_path, "scopes", "cloudsharing", "resources"
|
||||
)
|
||||
scan_for_files(directory, uuids_in_library)
|
||||
|
||||
verbose_("Scanning scopes syndication files")
|
||||
directory = joinpath(photosdb.library_path, "scopes", "syndication")
|
||||
scan_for_files(directory, uuids_in_library)
|
||||
|
||||
verbose_("Scanning scopes momentshared files")
|
||||
directory = joinpath(photosdb.library_path, "scopes", "momentshared")
|
||||
scan_for_files(directory, uuids_in_library)
|
||||
|
||||
# find orphans
|
||||
possible_orphans = []
|
||||
for uuid, files in uuids_in_library.items():
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
"""Click parameter types for osxphotos CLI"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import pathlib
|
||||
@ -18,6 +21,8 @@ from osxphotos.utils import expand_and_validate_filepath, load_function
|
||||
|
||||
__all__ = [
|
||||
"BitMathSize",
|
||||
"BooleanString",
|
||||
"CSVOptions",
|
||||
"DateOffset",
|
||||
"DateTimeISO8601",
|
||||
"DeprecatedPath",
|
||||
@ -302,3 +307,46 @@ class Longitude(click.ParamType):
|
||||
self.fail(
|
||||
f"Invalid longitude {value}. Must be a floating point number between -180 and 180."
|
||||
)
|
||||
|
||||
|
||||
class BooleanString(click.ParamType):
|
||||
"""A boolean string in the format True/False, Yes/No, T/F, Y/N, 1/0 (case insensitive)"""
|
||||
|
||||
name = "BooleanString"
|
||||
|
||||
def convert(self, value, param, ctx):
|
||||
if value.lower() in ["true", "yes", "t", "y", "1"]:
|
||||
return True
|
||||
elif value.lower() in ["false", "no", "f", "n", "0"]:
|
||||
return False
|
||||
else:
|
||||
self.fail(
|
||||
f"Invalid boolean string {value}. Must be one of True/False, Yes/No, T/F, Y/N, 1/0 (case insensitive)."
|
||||
)
|
||||
|
||||
|
||||
class CSVOptions(click.ParamType):
|
||||
"""A comma-separated list of option values, not case sensitive"""
|
||||
|
||||
name = "CSVOptions"
|
||||
|
||||
def __init__(self, options: list[str]):
|
||||
"""Initialize CSVOptions
|
||||
|
||||
Args:
|
||||
options: list of valid options as str
|
||||
|
||||
Note:
|
||||
The convert method returns a tuple[str, ...] of the options selected
|
||||
"""
|
||||
self._csv_options = options
|
||||
|
||||
def convert(self, value, param, ctx) -> tuple[str, ...]:
|
||||
values = value.split(",")
|
||||
values = [v.lower().strip() for v in values]
|
||||
for v in values:
|
||||
if v not in self._csv_options:
|
||||
self.fail(
|
||||
f"Invalid option {v}. Must be one of {','.join(self._csv_options)}"
|
||||
)
|
||||
return tuple(values)
|
||||
|
||||
@ -176,6 +176,18 @@ def inspect_photo(
|
||||
if photo.moment_info:
|
||||
properties.append(bold("Moment: ") + f"{photo.moment_info.title or '-'}")
|
||||
|
||||
if photo.shared_moment:
|
||||
info = photo.shared_moment_info
|
||||
title = info.title if info else "-"
|
||||
expiry = info.expiry_date.isoformat() if info and info.expiry_date else "-"
|
||||
share_url = info.share_url if info else "-"
|
||||
properties.append(
|
||||
bold("Shared Moment: ") + f"{title} expiry: {expiry} url: {share_url}"
|
||||
)
|
||||
|
||||
if photo.syndicated:
|
||||
...
|
||||
|
||||
if photo.comments:
|
||||
comments = [f"{c.user}: {c.text}" for c in photo.comments]
|
||||
properties.append(
|
||||
@ -260,6 +272,13 @@ def format_flags(photo: PhotoInfo) -> str:
|
||||
flags.append("in cloud")
|
||||
if photo.shared:
|
||||
flags.append("shared")
|
||||
if photo.syndicated:
|
||||
flags.append("syndicated") # sourcery skip
|
||||
flags.append(
|
||||
"saved to library" if photo.saved_to_library else "not saved to library"
|
||||
)
|
||||
if photo.shared_library:
|
||||
flags.append("shared iCloud library")
|
||||
|
||||
flag_str += f"{', '.join(flags) or '-'}"
|
||||
return flag_str
|
||||
|
||||
@ -52,7 +52,9 @@ MACOS_OPTIONS = make_click_option_decorator(
|
||||
@click.command()
|
||||
@DB_OPTION
|
||||
@JSON_OPTION
|
||||
@click.option("--count", is_flag=True, help="Print count of photos matching query and exit.")
|
||||
@click.option(
|
||||
"--count", is_flag=True, help="Print count of photos matching query and exit."
|
||||
)
|
||||
@QUERY_OPTIONS
|
||||
@DELETED_OPTIONS
|
||||
@MACOS_OPTIONS
|
||||
|
||||
@ -98,6 +98,11 @@ class ExportReportWriterCSV(ReportWriterABC):
|
||||
"cleanup_deleted_file",
|
||||
"cleanup_deleted_directory",
|
||||
"exported_album",
|
||||
"sidecar_user",
|
||||
"sidecar_user_error",
|
||||
"user_written",
|
||||
"user_skipped",
|
||||
"user_error",
|
||||
]
|
||||
|
||||
mode = "a" if append else "w"
|
||||
@ -197,9 +202,9 @@ class ExportReportWriterSQLite(ReportWriterABC):
|
||||
cursor = self._conn.cursor()
|
||||
cursor.execute(
|
||||
"INSERT INTO report "
|
||||
"(datetime, filename, exported, new, updated, skipped, exif_updated, touched, converted_to_jpeg, sidecar_xmp, sidecar_json, sidecar_exiftool, missing, error, exiftool_warning, exiftool_error, extended_attributes_written, extended_attributes_skipped, cleanup_deleted_file, cleanup_deleted_directory, exported_album, report_id) "
|
||||
"(datetime, filename, exported, new, updated, skipped, exif_updated, touched, converted_to_jpeg, sidecar_xmp, sidecar_json, sidecar_exiftool, missing, error, exiftool_warning, exiftool_error, extended_attributes_written, extended_attributes_skipped, cleanup_deleted_file, cleanup_deleted_directory, exported_album, report_id, sidecar_user, sidecar_user_error, user_written, user_skipped, user_error) " # noqa
|
||||
"VALUES "
|
||||
"(:datetime, :filename, :exported, :new, :updated, :skipped, :exif_updated, :touched, :converted_to_jpeg, :sidecar_xmp, :sidecar_json, :sidecar_exiftool, :missing, :error, :exiftool_warning, :exiftool_error, :extended_attributes_written, :extended_attributes_skipped, :cleanup_deleted_file, :cleanup_deleted_directory, :exported_album, :report_id);",
|
||||
"(:datetime, :filename, :exported, :new, :updated, :skipped, :exif_updated, :touched, :converted_to_jpeg, :sidecar_xmp, :sidecar_json, :sidecar_exiftool, :missing, :error, :exiftool_warning, :exiftool_error, :extended_attributes_written, :extended_attributes_skipped, :cleanup_deleted_file, :cleanup_deleted_directory, :exported_album, :report_id, :sidecar_user, :sidecar_user_error, :user_written, :user_skipped, :user_error);", # noqa
|
||||
data,
|
||||
)
|
||||
self._conn.commit()
|
||||
@ -262,6 +267,39 @@ class ExportReportWriterSQLite(ReportWriterABC):
|
||||
self._conn.cursor().execute("ALTER TABLE report ADD COLUMN report_id TEXT;")
|
||||
self._conn.commit()
|
||||
|
||||
# migrate report table and add sidecar_user column if needed (#1123)
|
||||
if "sidecar_user" not in sqlite_columns(self._conn, "report"):
|
||||
self._conn.cursor().execute(
|
||||
"ALTER TABLE report ADD COLUMN sidecar_user INTEGER;"
|
||||
)
|
||||
self._conn.commit()
|
||||
|
||||
# migrate report table and add sidecar_user_error if needed (#1123)
|
||||
if "sidecar_user_error" not in sqlite_columns(self._conn, "report"):
|
||||
self._conn.cursor().execute(
|
||||
"ALTER TABLE report ADD COLUMN sidecar_user_error TEXT;"
|
||||
)
|
||||
self._conn.commit()
|
||||
|
||||
# migrate report table and add user_written, skipped, error if needed (#1136)
|
||||
if "user_written" not in sqlite_columns(self._conn, "report"):
|
||||
self._conn.cursor().execute(
|
||||
"ALTER TABLE report ADD COLUMN user_written INTEGER;"
|
||||
)
|
||||
self._conn.commit()
|
||||
|
||||
if "user_skipped" not in sqlite_columns(self._conn, "report"):
|
||||
self._conn.cursor().execute(
|
||||
"ALTER TABLE report ADD COLUMN user_skipped INTEGER;"
|
||||
)
|
||||
self._conn.commit()
|
||||
|
||||
if "user_error" not in sqlite_columns(self._conn, "report"):
|
||||
self._conn.cursor().execute(
|
||||
"ALTER TABLE report ADD COLUMN user_error TEXT;"
|
||||
)
|
||||
self._conn.commit()
|
||||
|
||||
# create report_summary view
|
||||
c.execute(
|
||||
"""
|
||||
@ -347,6 +385,11 @@ def prepare_export_results_for_writing(
|
||||
"cleanup_deleted_file": false,
|
||||
"cleanup_deleted_directory": false,
|
||||
"exported_album": "",
|
||||
"sidecar_user": false,
|
||||
"sidecar_user_error": "",
|
||||
"user_written": false,
|
||||
"user_skipped": false,
|
||||
"user_error": "",
|
||||
}
|
||||
|
||||
for result in export_results.exported:
|
||||
@ -421,6 +464,28 @@ def prepare_export_results_for_writing(
|
||||
for result, album in export_results.exported_album:
|
||||
all_results[str(result)]["exported_album"] = album
|
||||
|
||||
for result in export_results.sidecar_user_written:
|
||||
all_results[str(result)]["sidecar_user"] = true
|
||||
all_results[str(result)]["exported"] = true
|
||||
|
||||
for result in export_results.sidecar_user_skipped:
|
||||
all_results[str(result)]["sidecar_user"] = true
|
||||
all_results[str(result)]["skipped"] = true
|
||||
|
||||
for result in export_results.sidecar_user_error:
|
||||
all_results[str(result[0])]["sidecar_user_error"] = result[1]
|
||||
|
||||
for result in export_results.user_written:
|
||||
all_results[str(result)]["user_written"] = true
|
||||
all_results[str(result)]["exported"] = true
|
||||
|
||||
for result in export_results.user_skipped:
|
||||
all_results[str(result)]["user_skipped"] = true
|
||||
all_results[str(result)]["skipped"] = true
|
||||
|
||||
for result in export_results.user_error:
|
||||
all_results[str(result[0])]["user_error"] = result[1]
|
||||
|
||||
return all_results
|
||||
|
||||
|
||||
|
||||
181
osxphotos/cli/sidecar.py
Normal file
181
osxphotos/cli/sidecar.py
Normal file
@ -0,0 +1,181 @@
|
||||
"""Generate custom sidecar files for use wit `osxphotos export` command and --sidecar-template option"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
from functools import cache
|
||||
from typing import Callable
|
||||
|
||||
import click
|
||||
from mako.template import Template
|
||||
|
||||
from osxphotos.cli.click_rich_echo import rich_echo_error
|
||||
from osxphotos.photoexporter import ExportResults
|
||||
from osxphotos.photoinfo import PhotoInfo
|
||||
from osxphotos.phototemplate import PhotoTemplate, RenderOptions
|
||||
|
||||
|
||||
@cache
|
||||
def get_template(template: str) -> Template:
|
||||
"""Get template from cache or load from file"""
|
||||
return Template(filename=template)
|
||||
|
||||
|
||||
def generate_user_sidecar(
|
||||
photo: PhotoInfo,
|
||||
export_results: ExportResults,
|
||||
sidecar_template: tuple[tuple[str, str, tuple[str, ...]], ...],
|
||||
exiftool_path: str,
|
||||
export_dir: str,
|
||||
dry_run: bool,
|
||||
verbose: Callable[..., None],
|
||||
) -> ExportResults:
|
||||
"""Generate custom sidecar files for use with `osxphotos export` command and --sidecar-template option
|
||||
|
||||
Args:
|
||||
photo: PhotoInfo object for photo
|
||||
export_results: ExportResults object
|
||||
sidecar_template: tuple of (template_file, filename_template) for sidecar template
|
||||
strip_sidecar: bool, strip whitespace and blank lines from sidecar
|
||||
exiftool_path: str, path to exiftool
|
||||
export_dir: str, path to export directory
|
||||
dry_run: bool, if True, do not actually write sidecar files
|
||||
verbose: Callable[..., None], verbose logging function
|
||||
|
||||
Returns:
|
||||
ExportResults object with sidecar_user_written and sidecar_user_skipped set
|
||||
"""
|
||||
sidecar_results = ExportResults()
|
||||
for (
|
||||
template_file,
|
||||
filename_template,
|
||||
options,
|
||||
) in sidecar_template:
|
||||
strip_whitespace = "strip_whitespace" in options
|
||||
strip_lines = "strip_lines" in options
|
||||
write_skipped = "write_skipped" in options
|
||||
skip_zero = "skip_zero" in options
|
||||
catch_errors = "catch_errors" in options
|
||||
|
||||
if not write_skipped:
|
||||
# skip writing sidecar if photo not exported
|
||||
# but if run with --update and --cleanup, a sidecar file may have been written
|
||||
# in the past, so check if it exists and if so keep it
|
||||
for filepath in export_results.skipped:
|
||||
template_filename = _render_sidecar_filename(
|
||||
photo=photo,
|
||||
filepath=filepath,
|
||||
filename_template=filename_template,
|
||||
export_dir=export_dir,
|
||||
exiftool_path=exiftool_path,
|
||||
)
|
||||
if template_filename and pathlib.Path(template_filename).exists():
|
||||
verbose(
|
||||
f"Skipping existing sidecar file [filepath]{template_filename}[/]"
|
||||
)
|
||||
sidecar_results.sidecar_user_skipped.append(template_filename)
|
||||
|
||||
# write sidecar files for exported and missing files (and skipped if write_skipped)
|
||||
files_to_process = export_results.exported + export_results.missing
|
||||
if write_skipped:
|
||||
files_to_process += export_results.skipped
|
||||
for filepath in files_to_process:
|
||||
template_filename = _render_sidecar_filename(
|
||||
photo=photo,
|
||||
filepath=filepath,
|
||||
filename_template=filename_template,
|
||||
export_dir=export_dir,
|
||||
exiftool_path=exiftool_path,
|
||||
)
|
||||
if not template_filename:
|
||||
raise click.BadOptionUsage(
|
||||
f"Invalid SIDECAR_FILENAME_TEMPLATE for --sidecar-template '{filename_template}'"
|
||||
)
|
||||
|
||||
verbose(f"Writing sidecar file [filepath]{template_filename}[/]")
|
||||
if error := _render_sidecar_and_write_data(
|
||||
template_file=template_file,
|
||||
photo=photo,
|
||||
template_filename=template_filename,
|
||||
filepath=filepath,
|
||||
strip_whitespace=strip_whitespace,
|
||||
strip_lines=strip_lines,
|
||||
skip_zero=skip_zero,
|
||||
catch_errors=catch_errors,
|
||||
verbose=verbose,
|
||||
dry_run=dry_run,
|
||||
):
|
||||
sidecar_results.sidecar_user_error.append((template_filename, error))
|
||||
else:
|
||||
sidecar_results.sidecar_user_written.append(template_filename)
|
||||
|
||||
print(sidecar_results)
|
||||
return sidecar_results
|
||||
|
||||
|
||||
def _render_sidecar_filename(
|
||||
photo: PhotoInfo,
|
||||
filepath: str,
|
||||
filename_template: str,
|
||||
export_dir: str,
|
||||
exiftool_path: str,
|
||||
):
|
||||
"""Render sidecar filename template"""
|
||||
render_options = RenderOptions(export_dir=export_dir, filepath=filepath)
|
||||
photo_template = PhotoTemplate(photo, exiftool_path=exiftool_path)
|
||||
template_filename, _ = photo_template.render(
|
||||
filename_template, options=render_options
|
||||
)
|
||||
template_filename = template_filename[0] if template_filename else None
|
||||
|
||||
return template_filename
|
||||
|
||||
|
||||
def _render_sidecar_and_write_data(
|
||||
template_file: str,
|
||||
photo: PhotoInfo,
|
||||
template_filename: str,
|
||||
filepath: str,
|
||||
strip_whitespace: bool,
|
||||
strip_lines: bool,
|
||||
skip_zero: bool,
|
||||
catch_errors: bool,
|
||||
verbose: Callable[..., None],
|
||||
dry_run: bool,
|
||||
) -> Exception | None:
|
||||
"""Render sidecar template and write data to file
|
||||
|
||||
Returns:
|
||||
None if no errors, otherwise Exception if catch_errors is True
|
||||
If catch_errors is False, raises exception if error
|
||||
"""
|
||||
sidecar = get_template(template_file)
|
||||
try:
|
||||
sidecar_data = sidecar.render(
|
||||
photo=photo,
|
||||
sidecar_path=pathlib.Path(template_filename),
|
||||
photo_path=pathlib.Path(filepath),
|
||||
)
|
||||
except Exception as e:
|
||||
if catch_errors:
|
||||
rich_echo_error(f"[error]Error rendering sidecar template: {e}[/]")
|
||||
return e
|
||||
raise e
|
||||
|
||||
if strip_whitespace:
|
||||
# strip whitespace
|
||||
sidecar_data = "\n".join(line.strip() for line in sidecar_data.split("\n"))
|
||||
if strip_lines:
|
||||
# strip blank lines
|
||||
sidecar_data = "\n".join(
|
||||
line for line in sidecar_data.split("\n") if line.strip()
|
||||
)
|
||||
if not dry_run:
|
||||
# write sidecar file
|
||||
if skip_zero and not sidecar_data:
|
||||
verbose(f"Skipping empty sidecar file [filepath]{template_filename}[/]")
|
||||
return
|
||||
with open(template_filename, "w") as f:
|
||||
f.write(sidecar_data)
|
||||
|
||||
return None
|
||||
@ -219,7 +219,7 @@ def _verbose_print_function(
|
||||
styled_args = []
|
||||
timestamp_str = f"{str(datetime.now())} -- " if timestamp else ""
|
||||
for arg in args:
|
||||
if type(arg) == str:
|
||||
if isinstance(arg, str):
|
||||
arg = timestamp_str + arg
|
||||
if "error" in arg.lower():
|
||||
arg = click.style(arg, fg=CLI_COLOR_ERROR)
|
||||
@ -236,7 +236,7 @@ def _verbose_print_function(
|
||||
timestamp_str = time_stamp() if timestamp else ""
|
||||
new_args = []
|
||||
for arg in args:
|
||||
if type(arg) == str:
|
||||
if isinstance(arg, str):
|
||||
if "error" in arg.lower():
|
||||
arg = f"[error]{arg}"
|
||||
if ERROR_EMOJI:
|
||||
@ -257,7 +257,7 @@ def _verbose_print_function(
|
||||
timestamp_str = time_stamp() if timestamp else ""
|
||||
new_args = []
|
||||
for arg in args:
|
||||
if type(arg) == str:
|
||||
if isinstance(arg, str):
|
||||
if "error" in arg.lower():
|
||||
arg = f"[error]{arg}"
|
||||
if ERROR_EMOJI:
|
||||
|
||||
Binary file not shown.
@ -58,7 +58,7 @@ def exiftool_can_write(suffix: str) -> bool:
|
||||
|
||||
def escape_str(s):
|
||||
"""escape string for use with exiftool -E"""
|
||||
if type(s) != str:
|
||||
if not isinstance(s, str):
|
||||
return s
|
||||
s = html.escape(s)
|
||||
s = s.replace("\n", "
")
|
||||
@ -69,7 +69,7 @@ def escape_str(s):
|
||||
|
||||
def unescape_str(s):
|
||||
"""unescape an HTML string returned by exiftool -E"""
|
||||
if type(s) != str:
|
||||
if not isinstance(s, str):
|
||||
return s
|
||||
# avoid " in values which result in json.loads() throwing an exception, #636
|
||||
s = s.replace(""", '\\"')
|
||||
|
||||
431
osxphotos/gitignorefile.py
Normal file
431
osxphotos/gitignorefile.py
Normal file
@ -0,0 +1,431 @@
|
||||
"""A spec-compliant `.gitignore` parser for Python.
|
||||
|
||||
Versioned from: https://github.com/excitoon/gitignorefile to add parse_pattern_list() function
|
||||
to apply .gitignore rules to a list of patterns that aren't actually a .gitignore file.
|
||||
|
||||
The original code was licensed under the MIT license, Copyright (c) 2022 Vladimir Chebotarev
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
from typing import Callable
|
||||
|
||||
DEFAULT_IGNORE_NAMES = [".gitignore", ".git/info/exclude"]
|
||||
|
||||
|
||||
def parse_pattern_list(
|
||||
patterns: list[str], base_path: str = None
|
||||
) -> Callable[[str], bool]:
|
||||
"""Parse a list of patterns and return a callable to match against a path.
|
||||
|
||||
Args:
|
||||
patterns (list[str]): List of patterns to match against.
|
||||
base_path (str): Base path for applying ignore rules.
|
||||
|
||||
Returns:
|
||||
Callable[[str], bool]: Callable which returns `True` if specified path is ignored.
|
||||
You can also pass `is_dir: bool` optional parameter if you know whether the specified path is a directory.
|
||||
"""
|
||||
rules = []
|
||||
for pattern in patterns:
|
||||
pattern = pattern.rstrip("\r\n")
|
||||
if rule := _rule_from_pattern(pattern):
|
||||
rules.append(rule)
|
||||
|
||||
return _IgnoreRules(rules, base_path).match
|
||||
|
||||
|
||||
def parse(path, base_path=None):
|
||||
"""Parses single `.gitignore` file.
|
||||
|
||||
Args:
|
||||
path (str): Path to `.gitignore` file.
|
||||
base_path (str): Base path for applying ignore rules.
|
||||
|
||||
Returns:
|
||||
Callable[[str], bool]: Callable which returns `True` if specified path is ignored.
|
||||
You can also pass `is_dir: bool` optional parameter if you know whether the specified path is a directory.
|
||||
"""
|
||||
|
||||
if base_path is None:
|
||||
base_path = os.path.dirname(path) or os.path.dirname(os.path.abspath(path))
|
||||
|
||||
rules = []
|
||||
with open(path) as ignore_file:
|
||||
for line in ignore_file:
|
||||
line = line.rstrip("\r\n")
|
||||
if rule := _rule_from_pattern(line):
|
||||
rules.append(rule)
|
||||
|
||||
return _IgnoreRules(rules, base_path).match
|
||||
|
||||
|
||||
def ignore(ignore_names=DEFAULT_IGNORE_NAMES):
|
||||
"""Returns `shutil.copytree()`-compatible ignore function for skipping ignored files.
|
||||
|
||||
It will check if file is ignored by any `.gitignore` in the directory tree.
|
||||
|
||||
Args:
|
||||
ignore_names (list[str], optional): List of names of ignore files.
|
||||
|
||||
Returns:
|
||||
Callable[[str, list[str]], list[str]]: Callable compatible with `shutil.copytree()`.
|
||||
"""
|
||||
|
||||
matches = Cache(ignore_names=ignore_names)
|
||||
return lambda root, names: {
|
||||
name for name in names if matches(os.path.join(root, name))
|
||||
}
|
||||
|
||||
|
||||
def ignored(path, is_dir=None, ignore_names=DEFAULT_IGNORE_NAMES):
|
||||
"""Checks if file is ignored by any `.gitignore` in the directory tree.
|
||||
|
||||
Args:
|
||||
path (str): Path to check against ignore rules.
|
||||
is_dir (bool, optional): Set if you know whether the specified path is a directory.
|
||||
ignore_names (list[str], optional): List of names of ignore files.
|
||||
|
||||
Returns:
|
||||
bool: `True` if the path is ignored.
|
||||
"""
|
||||
|
||||
return Cache(ignore_names=ignore_names)(path, is_dir=is_dir)
|
||||
|
||||
|
||||
class Cache:
|
||||
"""Caches information about different `.gitignore` files in the directory tree.
|
||||
|
||||
Allows to reduce number of queries to filesystem to mininum.
|
||||
"""
|
||||
|
||||
def __init__(self, ignore_names=DEFAULT_IGNORE_NAMES):
|
||||
"""Constructs `Cache` objects.
|
||||
|
||||
Args:
|
||||
ignore_names (list[str], optional): List of names of ignore files.
|
||||
"""
|
||||
|
||||
self.__ignore_names = ignore_names
|
||||
self.__gitignores = {}
|
||||
|
||||
def __call__(self, path, is_dir=None):
|
||||
"""Checks whether the specified path is ignored.
|
||||
|
||||
Args:
|
||||
path (str): Path to check against ignore rules.
|
||||
is_dir (bool, optional): Set if you know whether the specified path is a directory.
|
||||
"""
|
||||
|
||||
path = _Path(path)
|
||||
add_to_children = {}
|
||||
plain_paths = []
|
||||
for parent in path.parents():
|
||||
if parent.parts in self.__gitignores:
|
||||
break
|
||||
|
||||
ignore_paths = []
|
||||
for ignore_name in self.__ignore_names:
|
||||
ignore_path = parent.join(ignore_name)
|
||||
if ignore_path.isfile():
|
||||
ignore_paths.append(str(ignore_path))
|
||||
|
||||
if ignore_paths:
|
||||
matches = [
|
||||
parse(ignore_path, base_path=parent) for ignore_path in ignore_paths
|
||||
]
|
||||
add_to_children[parent] = (matches, plain_paths)
|
||||
plain_paths = []
|
||||
|
||||
else:
|
||||
plain_paths.append(parent)
|
||||
|
||||
else:
|
||||
parent = _Path(tuple()) # Null path.
|
||||
self.__gitignores[parent.parts] = []
|
||||
|
||||
for plain_path in plain_paths:
|
||||
# assert plain_path.parts not in self.__gitignores
|
||||
self.__gitignores[plain_path.parts] = self.__gitignores[parent.parts]
|
||||
|
||||
for parent, (_, parent_plain_paths) in reversed(list(add_to_children.items())):
|
||||
# assert parent.parts not in self.__gitignores
|
||||
self.__gitignores[parent.parts] = self.__gitignores[
|
||||
parent.parts[:-1]
|
||||
].copy()
|
||||
for parent_to_add, (gitignores_to_add, _) in reversed(
|
||||
list(add_to_children.items())
|
||||
):
|
||||
self.__gitignores[parent.parts].extend(gitignores_to_add)
|
||||
if parent_to_add == parent:
|
||||
break
|
||||
|
||||
self.__gitignores[parent.parts].reverse()
|
||||
|
||||
for plain_path in parent_plain_paths:
|
||||
# assert plain_path.parts not in self.__gitignores
|
||||
self.__gitignores[plain_path.parts] = self.__gitignores[parent.parts]
|
||||
|
||||
# This parent comes either from first or second loop.
|
||||
return any((m(path, is_dir=is_dir) for m in self.__gitignores[parent.parts]))
|
||||
|
||||
|
||||
class _Path:
|
||||
def __init__(self, path):
|
||||
if isinstance(path, (str, bytes, os.PathLike)):
|
||||
abs_path = os.path.abspath(path)
|
||||
self.__parts = tuple(_path_split(abs_path))
|
||||
self.__joined = abs_path
|
||||
self.__is_dir = None
|
||||
|
||||
else:
|
||||
self.__parts = path
|
||||
self.__joined = None
|
||||
self.__is_dir = None
|
||||
|
||||
@property
|
||||
def parts(self):
|
||||
return self.__parts
|
||||
|
||||
def join(self, name):
|
||||
return _Path(self.__parts + (name,))
|
||||
|
||||
def relpath(self, base_path):
|
||||
if self.__parts[: len(base_path.__parts)] == base_path.__parts:
|
||||
return "/".join(self.__parts[len(base_path.__parts) :])
|
||||
|
||||
else:
|
||||
return None
|
||||
|
||||
def parents(self):
|
||||
for i in range(len(self.__parts) - 1, 0, -1):
|
||||
yield _Path(self.__parts[:i])
|
||||
|
||||
def isfile(self):
|
||||
return os.path.isfile(str(self))
|
||||
|
||||
def isdir(self):
|
||||
if self.__is_dir is not None:
|
||||
return self.__is_dir
|
||||
self.__is_dir = os.path.isdir(str(self))
|
||||
return self.__is_dir
|
||||
|
||||
def __str__(self):
|
||||
if self.__joined is None:
|
||||
self.__joined = (
|
||||
os.sep.join(self.__parts) if self.__parts != ("",) else os.sep
|
||||
)
|
||||
return self.__joined
|
||||
|
||||
|
||||
def _rule_from_pattern(pattern):
|
||||
# Takes a `.gitignore` match pattern, such as "*.py[cod]" or "**/*.bak",
|
||||
# and returns an `_IgnoreRule` suitable for matching against files and
|
||||
# directories. Patterns which do not match files, such as comments
|
||||
# and blank lines, will return `None`.
|
||||
|
||||
# Early returns follow
|
||||
# Discard comments and separators
|
||||
if not pattern.lstrip() or pattern.lstrip().startswith("#"):
|
||||
return
|
||||
|
||||
# Discard anything with more than two consecutive asterisks
|
||||
if "***" in pattern:
|
||||
return
|
||||
|
||||
# Strip leading bang before examining double asterisks
|
||||
if pattern.startswith("!"):
|
||||
negation = True
|
||||
pattern = pattern[1:]
|
||||
else:
|
||||
negation = False
|
||||
|
||||
# Discard anything with invalid double-asterisks -- they can appear
|
||||
# at the start or the end, or be surrounded by slashes
|
||||
for m in re.finditer("\\*\\*", pattern):
|
||||
start_index = m.start()
|
||||
if (
|
||||
start_index != 0
|
||||
and start_index != len(pattern) - 2
|
||||
and (pattern[start_index - 1] != "/" or pattern[start_index + 2] != "/")
|
||||
):
|
||||
return
|
||||
|
||||
# Special-casing '/', which doesn't match any files or directories
|
||||
if pattern.rstrip() == "/":
|
||||
return
|
||||
|
||||
directory_only = pattern.endswith("/")
|
||||
|
||||
# A slash is a sign that we're tied to the `base_path` of our rule
|
||||
# set.
|
||||
anchored = "/" in pattern[:-1]
|
||||
|
||||
if pattern.startswith("/"):
|
||||
pattern = pattern[1:]
|
||||
if pattern.startswith("**"):
|
||||
pattern = pattern[2:]
|
||||
anchored = False
|
||||
if pattern.startswith("/"):
|
||||
pattern = pattern[1:]
|
||||
if pattern.endswith("/"):
|
||||
pattern = pattern[:-1]
|
||||
|
||||
# patterns with leading hashes are escaped with a backslash in front, unescape it
|
||||
if pattern.startswith("\\#"):
|
||||
pattern = pattern[1:]
|
||||
|
||||
# trailing spaces are ignored unless they are escaped with a backslash
|
||||
i = len(pattern) - 1
|
||||
striptrailingspaces = True
|
||||
while i > 1 and pattern[i] == " ":
|
||||
if pattern[i - 1] == "\\":
|
||||
pattern = pattern[: i - 1] + pattern[i:]
|
||||
i -= 1
|
||||
striptrailingspaces = False
|
||||
else:
|
||||
if striptrailingspaces:
|
||||
pattern = pattern[:i]
|
||||
i -= 1
|
||||
|
||||
regexp = _fnmatch_pathname_to_regexp(pattern, anchored, directory_only)
|
||||
return _IgnoreRule(regexp, negation, directory_only)
|
||||
|
||||
|
||||
class _IgnoreRules:
|
||||
def __init__(self, rules, base_path):
|
||||
self.__rules = rules
|
||||
self.__can_return_immediately = not any((r.negation for r in rules))
|
||||
self.__base_path = (
|
||||
_Path(base_path) if not isinstance(base_path, _Path) else base_path
|
||||
)
|
||||
|
||||
def match(self, path, is_dir=None):
|
||||
if not isinstance(path, _Path):
|
||||
path = _Path(path)
|
||||
|
||||
rel_path = path.relpath(self.__base_path)
|
||||
|
||||
if rel_path is not None:
|
||||
if is_dir is None:
|
||||
is_dir = path.isdir() # TODO Pass callable here.
|
||||
|
||||
if self.__can_return_immediately:
|
||||
return any((r.match(rel_path, is_dir) for r in self.__rules))
|
||||
|
||||
else:
|
||||
matched = False
|
||||
for rule in self.__rules:
|
||||
if rule.match(rel_path, is_dir):
|
||||
matched = not rule.negation
|
||||
|
||||
else:
|
||||
return matched
|
||||
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
class _IgnoreRule:
|
||||
def __init__(self, regexp, negation, directory_only):
|
||||
self.__regexp = re.compile(regexp)
|
||||
self.__negation = negation
|
||||
self.__directory_only = directory_only
|
||||
self.__match = self.__regexp.match
|
||||
|
||||
@property
|
||||
def regexp(self):
|
||||
return self.__regexp
|
||||
|
||||
@property
|
||||
def negation(self):
|
||||
return self.__negation
|
||||
|
||||
def match(self, rel_path, is_dir):
|
||||
m = self.__match(rel_path)
|
||||
|
||||
# If we need a directory, check there is something after slash and if there is not, target must be a directory.
|
||||
# If there is something after slash then it's a directory irrelevant to type of target.
|
||||
# `self.directory_only` implies we have group number 1.
|
||||
# N.B. Question mark inside a group without a name can shift indices. :(
|
||||
return m and (not self.__directory_only or m.group(1) is not None or is_dir)
|
||||
|
||||
|
||||
if os.altsep is not None:
|
||||
_all_seps_expr = f"[{re.escape(os.sep)}{re.escape(os.altsep)}]"
|
||||
_path_split = lambda path: re.split(_all_seps_expr, path) # noqa: E731
|
||||
|
||||
else:
|
||||
_path_split = lambda path: path.split(os.sep) # noqa: E731
|
||||
|
||||
|
||||
def _fnmatch_pathname_to_regexp(pattern, anchored, directory_only):
|
||||
# Implements `fnmatch` style-behavior, as though with `FNM_PATHNAME` flagged;
|
||||
# the path separator will not match shell-style `*` and `.` wildcards.
|
||||
|
||||
# Frustratingly, python's fnmatch doesn't provide the FNM_PATHNAME
|
||||
# option that `.gitignore`'s behavior depends on.
|
||||
|
||||
if not pattern:
|
||||
if directory_only:
|
||||
return "[^/]+(/.+)?$" # Empty name means no path fragment.
|
||||
|
||||
else:
|
||||
return ".*"
|
||||
|
||||
i, n = 0, len(pattern)
|
||||
|
||||
res = ["(?:^|.+/)" if not anchored else ""]
|
||||
while i < n:
|
||||
c = pattern[i]
|
||||
i += 1
|
||||
if c == "*":
|
||||
if i < n and pattern[i] == "*":
|
||||
i += 1
|
||||
if i < n and pattern[i] == "/":
|
||||
i += 1
|
||||
res.append("(.+/)?") # `/**/` matches `/`.
|
||||
|
||||
else:
|
||||
res.append(".*")
|
||||
|
||||
else:
|
||||
res.append("[^/]*")
|
||||
|
||||
elif c == "?":
|
||||
res.append("[^/]")
|
||||
|
||||
elif c == "[":
|
||||
j = i
|
||||
if j < n and pattern[j] == "!":
|
||||
j += 1
|
||||
if j < n and pattern[j] == "]":
|
||||
j += 1
|
||||
while j < n and pattern[j] != "]":
|
||||
j += 1
|
||||
|
||||
if j >= n:
|
||||
res.append("\\[")
|
||||
else:
|
||||
stuff = pattern[i:j].replace("\\", "\\\\")
|
||||
i = j + 1
|
||||
if stuff[0] == "!":
|
||||
stuff = f"^{stuff[1:]}"
|
||||
elif stuff[0] == "^":
|
||||
stuff = f"\\{stuff}"
|
||||
res.append(f"[{stuff}]")
|
||||
|
||||
else:
|
||||
res.append(re.escape(c))
|
||||
|
||||
if (
|
||||
directory_only
|
||||
): # In this case we are interested if there is something after slash.
|
||||
res.append("(/.+)?$")
|
||||
|
||||
else:
|
||||
res.append("(?:/.+)?$")
|
||||
|
||||
return "".join(res)
|
||||
@ -266,7 +266,51 @@ class StagedFiles:
|
||||
|
||||
|
||||
class ExportResults:
|
||||
"""Results class which holds export results for export"""
|
||||
"""Results class which holds export results for export
|
||||
|
||||
Args:
|
||||
converted_to_jpeg: list of files converted to jpeg
|
||||
deleted_directories: list of directories deleted
|
||||
deleted_files: list of files deleted
|
||||
error: list of tuples of (filename, error) for any errors generated during export
|
||||
exif_updated: list of files where exif data was updated with exiftool
|
||||
exiftool_error: list of tuples of (filename, error) for any errors generated by exiftool
|
||||
exiftool_warning: list of tuples of (filename, warning) for any warnings generated by exiftool
|
||||
exported: list of files exported
|
||||
exported_album: list of tuples of (file, album) for any files exported to an album
|
||||
metadata_changed: list of filenames that had metadata changes since last export
|
||||
missing: list of files that were missing
|
||||
missing_album: list of tuples of (file, album) for any files that were missing from an album
|
||||
new: list of files that were new
|
||||
aae_written: list of files where .AAE file was written
|
||||
sidecar_exiftool_skipped: list of files where exiftool sidecar was skipped
|
||||
sidecar_exiftool_written: list of files where exiftool sidecar was written
|
||||
sidecar_json_skipped: list of files where json sidecar was skipped
|
||||
sidecar_json_written: list of files where json sidecar was written
|
||||
sidecar_xmp_skipped: list of files where xmp sidecar was skipped
|
||||
sidecar_xmp_written: list of files where xmp sidecar was written
|
||||
sidecar_user_written: list of files where user sidecar was written
|
||||
sidecar_user_skipped: list of files where user sidecar was skipped
|
||||
sidecar_user_error: list of tuples of (filename, error) for any errors generated by user sidecar
|
||||
skipped: list of files that were skipped
|
||||
skipped_album: list of tuples of (file, album) for any files that were skipped from an album
|
||||
to_touch: list of files that were touched
|
||||
touched: list of files that were touched
|
||||
updated: list of files that were updated
|
||||
xattr_skipped: list of files where xattr was skipped
|
||||
xattr_written: list of files where xattr was written
|
||||
user_written: list of files written by user post_function
|
||||
user_skipped: list of files skipped by user post_function
|
||||
user_error: list of tuples of (filename, error) for any errors generated by user post_function
|
||||
|
||||
Notes:
|
||||
Each attribute is a list of files or None if no files for that attribute.
|
||||
Error and warning attributes are a list of tuples of (filename, error) where filename is the file that caused the error and error is the error message.
|
||||
Album attributes are a list of tuples of (file, album) where file is the file exported and album is the album it was exported to.
|
||||
ExportResults can be added together with the += operator to combine results as the export progresses.
|
||||
"""
|
||||
|
||||
# Note: __init__ docs above added in the class docstring so they are picked up by sphinx
|
||||
|
||||
__slots__ = [
|
||||
"_datetime",
|
||||
@ -290,6 +334,9 @@ class ExportResults:
|
||||
"sidecar_json_written",
|
||||
"sidecar_xmp_skipped",
|
||||
"sidecar_xmp_written",
|
||||
"sidecar_user_written",
|
||||
"sidecar_user_skipped",
|
||||
"sidecar_user_error",
|
||||
"skipped",
|
||||
"skipped_album",
|
||||
"to_touch",
|
||||
@ -297,38 +344,51 @@ class ExportResults:
|
||||
"updated",
|
||||
"xattr_skipped",
|
||||
"xattr_written",
|
||||
"user_written",
|
||||
"user_skipped",
|
||||
"user_error",
|
||||
]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
converted_to_jpeg=None,
|
||||
deleted_directories=None,
|
||||
deleted_files=None,
|
||||
error=None,
|
||||
exif_updated=None,
|
||||
exiftool_error=None,
|
||||
exiftool_warning=None,
|
||||
exported=None,
|
||||
exported_album=None,
|
||||
metadata_changed=None,
|
||||
missing=None,
|
||||
missing_album=None,
|
||||
new=None,
|
||||
aae_written=None,
|
||||
sidecar_exiftool_skipped=None,
|
||||
sidecar_exiftool_written=None,
|
||||
sidecar_json_skipped=None,
|
||||
sidecar_json_written=None,
|
||||
sidecar_xmp_skipped=None,
|
||||
sidecar_xmp_written=None,
|
||||
skipped=None,
|
||||
skipped_album=None,
|
||||
to_touch=None,
|
||||
touched=None,
|
||||
updated=None,
|
||||
xattr_skipped=None,
|
||||
xattr_written=None,
|
||||
converted_to_jpeg: list[str] | None = None,
|
||||
deleted_directories: list[str] | None = None,
|
||||
deleted_files: list[str] | None = None,
|
||||
error: list[str] | None = None,
|
||||
exif_updated: list[str] | None = None,
|
||||
exiftool_error: list[tuple[str, str]] | None = None,
|
||||
exiftool_warning: list[tuple[str, str]] | None = None,
|
||||
exported: list[str] | None = None,
|
||||
exported_album: list[tuple[str, str]] | None = None,
|
||||
metadata_changed: list[str] | None = None,
|
||||
missing: list[str] | None = None,
|
||||
missing_album: list[tuple[str, str]] | None = None,
|
||||
new: list[str] | None = None,
|
||||
aae_written: list[str] | None = None,
|
||||
sidecar_exiftool_skipped: list[str] | None = None,
|
||||
sidecar_exiftool_written: list[str] | None = None,
|
||||
sidecar_json_skipped: list[str] | None = None,
|
||||
sidecar_json_written: list[str] | None = None,
|
||||
sidecar_xmp_skipped: list[str] | None = None,
|
||||
sidecar_xmp_written: list[str] | None = None,
|
||||
sidecar_user_written: list[str] | None = None,
|
||||
sidecar_user_skipped: list[str] | None = None,
|
||||
sidecar_user_error: list[tuple[str, str]] | None = None,
|
||||
skipped: list[str] | None = None,
|
||||
skipped_album: list[tuple[str, str]] | None = None,
|
||||
to_touch: list[str] | None = None,
|
||||
touched: list[str] | None = None,
|
||||
updated: list[str] | None = None,
|
||||
xattr_skipped: list[str] | None = None,
|
||||
xattr_written: list[str] | None = None,
|
||||
user_written: list[str] | None = None,
|
||||
user_skipped: list[str] | None = None,
|
||||
user_error: list[tuple[str, str]] | None = None,
|
||||
):
|
||||
"""ExportResults data class to hold results of export.
|
||||
|
||||
See class docstring for details.
|
||||
"""
|
||||
local_vars = locals()
|
||||
self._datetime = datetime.now().isoformat()
|
||||
for attr in self.attributes:
|
||||
@ -361,11 +421,17 @@ class ExportResults:
|
||||
+ self.sidecar_exiftool_skipped
|
||||
+ self.sidecar_xmp_written
|
||||
+ self.sidecar_xmp_skipped
|
||||
+ self.sidecar_user_written
|
||||
+ self.sidecar_user_skipped
|
||||
+ self.missing
|
||||
+ self.user_written
|
||||
+ self.user_skipped
|
||||
)
|
||||
files += [x[0] for x in self.exiftool_warning]
|
||||
files += [x[0] for x in self.exiftool_error]
|
||||
files += [x[0] for x in self.error]
|
||||
files += [x[0] for x in self.sidecar_user_error]
|
||||
files += [x[0] for x in self.user_error]
|
||||
|
||||
return list(set(files))
|
||||
|
||||
@ -1433,7 +1499,8 @@ class PhotoExporter:
|
||||
if options.export_as_hardlink:
|
||||
try:
|
||||
if aae_dest.exists() and any(
|
||||
[options.overwrite, options.update, options.force_update]):
|
||||
[options.overwrite, options.update, options.force_update]
|
||||
):
|
||||
try:
|
||||
options.fileutil.unlink(aae_dest)
|
||||
except Exception as e:
|
||||
|
||||
@ -65,6 +65,8 @@ from .platform import assert_macos, is_macos
|
||||
from .query_builder import get_query
|
||||
from .scoreinfo import ScoreInfo
|
||||
from .searchinfo import SearchInfo
|
||||
from .shareinfo import ShareInfo, get_moment_share_info, get_share_info
|
||||
from .shareparticipant import ShareParticipant, get_share_participants
|
||||
from .uti import get_preferred_uti_extension, get_uti_for_extension
|
||||
from .utils import _get_resource_loc, hexdigest, list_directory
|
||||
|
||||
@ -173,6 +175,16 @@ class PhotoInfo:
|
||||
"""Returns candidate path for original photo on Photos >= version 5"""
|
||||
if self._info["shared"]:
|
||||
return self._path_5_shared()
|
||||
if (
|
||||
self.shared_moment
|
||||
and self._db.photos_version >= 7
|
||||
and self._path_shared_moment()
|
||||
):
|
||||
# path for photos in shared moments if it's in the shared moment folder
|
||||
# the file may also be in the originals folder which the next check will catch
|
||||
# check shared_moment first as a photo can be both a shared moment and syndicated
|
||||
# and if so, will be in the shared moment folder
|
||||
return self._path_shared_moment()
|
||||
if self.syndicated and not self.saved_to_library:
|
||||
# path for "shared with you" syndicated photos that have not yet been saved to the library
|
||||
return self._path_syndication()
|
||||
@ -216,8 +228,8 @@ class PhotoInfo:
|
||||
)
|
||||
|
||||
def _path_syndication(self):
|
||||
"""Return path for syndicated photo on Photos >= version 8"""
|
||||
# Photos 8+ stores syndicated photos in a separate directory
|
||||
"""Return path for syndicated photo on Photos >= version 7"""
|
||||
# Photos 7+ stores syndicated photos in a separate directory
|
||||
# in ~/Photos Library.photoslibrary/scopes/syndication/originals/X/UUID.ext
|
||||
# where X is first digit of UUID
|
||||
syndication_path = "scopes/syndication/originals"
|
||||
@ -230,6 +242,21 @@ class PhotoInfo:
|
||||
)
|
||||
return path if os.path.isfile(path) else None
|
||||
|
||||
def _path_shared_moment(self):
|
||||
"""Return path for shared moment photo on Photos >= version 7"""
|
||||
# Photos 7+ stores shared moment photos in a separate directory
|
||||
# in ~/Photos Library.photoslibrary/scopes/momentshared/originals/X/UUID.ext
|
||||
# where X is first digit of UUID
|
||||
momentshared_path = "scopes/momentshared/originals"
|
||||
uuid_dir = self.uuid[0]
|
||||
path = os.path.join(
|
||||
self._db._library_path,
|
||||
momentshared_path,
|
||||
uuid_dir,
|
||||
self.filename,
|
||||
)
|
||||
return path if os.path.isfile(path) else None
|
||||
|
||||
def _path_4(self):
|
||||
"""Returns candidate path for original photo on Photos <= version 4"""
|
||||
if self._info["has_raw"]:
|
||||
@ -350,7 +377,7 @@ class PhotoInfo:
|
||||
)
|
||||
|
||||
def _path_edited_4(self) -> str | None:
|
||||
"""return path_edited for Photos <= 4; modified version of code in PhotoInfo to debug #859"""
|
||||
"""return path_edited for Photos <= 4; #859"""
|
||||
|
||||
if not self._info["hasAdjustments"]:
|
||||
return None
|
||||
@ -455,7 +482,7 @@ class PhotoInfo:
|
||||
|
||||
# In Photos 5, raw is in same folder as original but with _4.ext
|
||||
# Unless "Copy Items to the Photos Library" is not checked
|
||||
# then RAW image is not renamed but has same name is jpeg buth with raw extension
|
||||
# then RAW image is not renamed but has same name is jpeg but with raw extension
|
||||
# Current implementation finds images with the correct raw UTI extension
|
||||
# in same folder as the original and with same stem as original in form: original_stem*.raw_ext
|
||||
# TODO: I don't like this -- would prefer a more deterministic approach but until I have more
|
||||
@ -525,6 +552,7 @@ class PhotoInfo:
|
||||
f"MISSING PATH: RAW photo for UUID {self._uuid} should be at {photopath} but does not appear to exist"
|
||||
)
|
||||
photopath = None
|
||||
return photopath
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
@ -910,6 +938,8 @@ class PhotoInfo:
|
||||
elif self.live_photo and self.path and not self.ismissing:
|
||||
if self.shared:
|
||||
return self._path_live_photo_shared_5()
|
||||
if self.shared_moment and self._db.photos_version >= 7:
|
||||
return self._path_live_shared_moment()
|
||||
if self.syndicated and not self.saved_to_library:
|
||||
# syndicated ("Shared with you") photos not yet saved to library
|
||||
return self._path_live_syndicated()
|
||||
@ -972,8 +1002,8 @@ class PhotoInfo:
|
||||
return photopath
|
||||
|
||||
def _path_live_syndicated(self):
|
||||
"""Return path for live syndicated photo on Photos >= version 8"""
|
||||
# Photos 8+ stores live syndicated photos in a separate directory
|
||||
"""Return path for live syndicated photo on Photos >= version 7"""
|
||||
# Photos 7+ stores live syndicated photos in a separate directory
|
||||
# in ~/Photos Library.photoslibrary/scopes/syndication/originals/X/UUID_3.mov
|
||||
# where X is first digit of UUID
|
||||
syndication_path = "scopes/syndication/originals"
|
||||
@ -987,6 +1017,22 @@ class PhotoInfo:
|
||||
)
|
||||
return live_photo if os.path.isfile(live_photo) else None
|
||||
|
||||
def _path_live_shared_moment(self):
|
||||
"""Return path for live shared moment photo on Photos >= version 7"""
|
||||
# Photos 7+ stores live shared moment photos in a separate directory
|
||||
# in ~/Photos Library.photoslibrary/scopes/momentshared/originals/X/UUID_3.mov
|
||||
# where X is first digit of UUID
|
||||
shared_moment_path = "scopes/momentshared/originals"
|
||||
uuid_dir = self.uuid[0]
|
||||
filename = f"{pathlib.Path(self.filename).stem}_3.mov"
|
||||
live_photo = os.path.join(
|
||||
self._db._library_path,
|
||||
shared_moment_path,
|
||||
uuid_dir,
|
||||
filename,
|
||||
)
|
||||
return live_photo if os.path.isfile(live_photo) else None
|
||||
|
||||
@cached_property
|
||||
def path_derivatives(self) -> list[str]:
|
||||
"""Return any derivative (preview) images associated with the photo as a list of paths, sorted by file size (largest first)"""
|
||||
@ -997,19 +1043,29 @@ class PhotoInfo:
|
||||
return self._path_derivatives_5_shared()
|
||||
|
||||
directory = self._uuid[0] # first char of uuid
|
||||
if self.syndicated and not self.saved_to_library:
|
||||
if self.shared_moment and self._db.photos_version >= 7:
|
||||
# shared moments
|
||||
derivative_path = "scopes/momentshared/resources/derivatives"
|
||||
thumb_path = (
|
||||
f"{derivative_path}/masters/{directory}/{self.uuid}_4_5005_c.jpeg"
|
||||
)
|
||||
elif self.syndicated and not self.saved_to_library:
|
||||
# syndicated ("Shared with you") photos not yet saved to library
|
||||
derivative_path = "scopes/syndication/resources/derivatives"
|
||||
thumb_path = (
|
||||
f"{derivative_path}/masters/{directory}/{self.uuid}_4_5005_c.jpeg"
|
||||
)
|
||||
else:
|
||||
derivative_path = f"resources/derivatives/{directory}"
|
||||
derivative_path = "resources/derivatives"
|
||||
thumb_path = (
|
||||
f"resources/derivatives/masters/{directory}/{self.uuid}_4_5005_c.jpeg"
|
||||
)
|
||||
|
||||
derivative_path = pathlib.Path(self._db._library_path).joinpath(derivative_path)
|
||||
derivative_path = (
|
||||
pathlib.Path(self._db._library_path)
|
||||
.joinpath(derivative_path)
|
||||
.joinpath(directory)
|
||||
)
|
||||
thumb_path = pathlib.Path(self._db._library_path).joinpath(thumb_path)
|
||||
|
||||
# find all files that start with uuid in derivative path
|
||||
@ -1349,9 +1405,9 @@ class PhotoInfo:
|
||||
def syndicated(self) -> bool | None:
|
||||
"""Return true if photo was shared via syndication (e.g. via Messages, etc.);
|
||||
these are photos that appear in "Shared with you" album.
|
||||
Photos 8+ only; returns None if not Photos 8+.
|
||||
Photos 7+ only; returns None if not Photos 7+.
|
||||
"""
|
||||
if self._db.photos_version < 8:
|
||||
if self._db.photos_version < 7:
|
||||
return None
|
||||
|
||||
try:
|
||||
@ -1366,10 +1422,10 @@ class PhotoInfo:
|
||||
def saved_to_library(self) -> bool | None:
|
||||
"""Return True if syndicated photo has been saved to library;
|
||||
returns False if photo is not syndicated or has not been saved to the library.
|
||||
Returns None if not Photos 8+.
|
||||
Syndicated photos are photos that appear in "Shared with you" album; Photos 8+ only.
|
||||
Returns None if not Photos 7+.
|
||||
Syndicated photos are photos that appear in "Shared with you" album; Photos 7+ only.
|
||||
"""
|
||||
if self._db.photos_version < 8:
|
||||
if self._db.photos_version < 7:
|
||||
return None
|
||||
|
||||
try:
|
||||
@ -1377,6 +1433,46 @@ class PhotoInfo:
|
||||
except KeyError:
|
||||
return False
|
||||
|
||||
@cached_property
|
||||
def shared_moment(self) -> bool:
|
||||
"""Returns True if photo is part of a shared moment otherwise False (Photos 7+ only)"""
|
||||
return bool(self._info["moment_share"])
|
||||
|
||||
@cached_property
|
||||
def shared_moment_info(self) -> ShareInfo | None:
|
||||
"""Returns ShareInfo object with information about the shared moment the photo is part of (Photos 7+ only)"""
|
||||
if self._db.photos_version < 7:
|
||||
return None
|
||||
|
||||
try:
|
||||
return get_moment_share_info(self._db, self.uuid)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
@cached_property
|
||||
def share_info(self) -> ShareInfo | None:
|
||||
"""Returns ShareInfo object with information about the shared photo in a shared iCloud library (Photos 8+ only) (currently experimental)"""
|
||||
if self._db.photos_version < 8:
|
||||
return None
|
||||
|
||||
try:
|
||||
return get_share_info(self._db, self.uuid)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
@cached_property
|
||||
def shared_library(self) -> bool:
|
||||
"""Returns True if photo is in a shared iCloud library otherwise False (Photos 8+ only)"""
|
||||
# TODO: this is just a guess right now as I don't currently use shared libraries
|
||||
return bool(self._info["active_library_participation_state"])
|
||||
|
||||
@cached_property
|
||||
def share_participants(self) -> list[ShareParticipant]:
|
||||
"""Returns list of ShareParticpant objects with information on who the photo is shared with (Photos 8+ only)"""
|
||||
if self._db.photos_version < 8:
|
||||
return []
|
||||
return get_share_participants(self._db, self.uuid)
|
||||
|
||||
@property
|
||||
def labels(self):
|
||||
"""returns list of labels applied to photo by Photos image categorization
|
||||
@ -1879,6 +1975,10 @@ class PhotoInfo:
|
||||
place = self.place.asdict() if self.place else {}
|
||||
score = dataclasses.asdict(self.score) if self.score else {}
|
||||
|
||||
# do not add any new properties to data_dict as this is used by export to determine
|
||||
# if a photo needs to be re-exported and adding new properties may cause all photos
|
||||
# to be re-exported
|
||||
# see below `if not shallow:`
|
||||
dict_data = {
|
||||
"albums": self.albums,
|
||||
"burst": self.burst,
|
||||
@ -1953,6 +2053,7 @@ class PhotoInfo:
|
||||
}
|
||||
|
||||
# non-shallow keys
|
||||
# add any new properties here
|
||||
if not shallow:
|
||||
dict_data["album_info"] = [album.asdict() for album in self.album_info]
|
||||
dict_data["path_derivatives"] = self.path_derivatives
|
||||
@ -1980,6 +2081,10 @@ class PhotoInfo:
|
||||
if self.search_info_normalized
|
||||
else {}
|
||||
)
|
||||
dict_data["syndicated"] = self.syndicated
|
||||
dict_data["saved_to_library"] = self.saved_to_library
|
||||
dict_data["shared_moment"] = self.shared_moment
|
||||
dict_data["shared_library"] = self.shared_library
|
||||
|
||||
return dict_data
|
||||
|
||||
|
||||
@ -4,4 +4,8 @@ Processes a Photos.app library database to extract information about photos
|
||||
"""
|
||||
|
||||
from .photosdb import PhotosDB
|
||||
from .photosdb_utils import get_db_model_version, get_db_version, get_model_version
|
||||
from .photosdb_utils import (
|
||||
get_db_version,
|
||||
get_model_version,
|
||||
get_photos_version_from_model,
|
||||
)
|
||||
|
||||
@ -179,6 +179,8 @@ def _process_faceinfo_5(photosdb):
|
||||
db = photosdb._tmp_db
|
||||
|
||||
asset_table = _DB_TABLE_NAMES[photosdb._photos_ver]["ASSET"]
|
||||
asset_fk = _DB_TABLE_NAMES[photosdb._photos_ver]["DETECTED_FACE_ASSET_FK"]
|
||||
person_fk = _DB_TABLE_NAMES[photosdb._photos_ver]["DETECTED_FACE_PERSON_FK"]
|
||||
|
||||
(conn, cursor) = sqlite_open_ro(db)
|
||||
|
||||
@ -188,7 +190,7 @@ def _process_faceinfo_5(photosdb):
|
||||
ZDETECTEDFACE.Z_PK,
|
||||
{asset_table}.ZUUID,
|
||||
ZDETECTEDFACE.ZUUID,
|
||||
ZDETECTEDFACE.ZPERSON,
|
||||
{person_fk},
|
||||
ZPERSON.ZFULLNAME,
|
||||
ZDETECTEDFACE.ZAGETYPE,
|
||||
NULL, -- ZDETECTEDFACE.ZBALDTYPE (Removed in Monterey)
|
||||
@ -225,8 +227,8 @@ def _process_faceinfo_5(photosdb):
|
||||
NULL, -- ZDETECTEDFACE.ZYAW,
|
||||
ZDETECTEDFACE.ZMASTERIDENTIFIER
|
||||
FROM ZDETECTEDFACE
|
||||
JOIN {asset_table} ON {asset_table}.Z_PK = ZDETECTEDFACE.ZASSET
|
||||
JOIN ZPERSON ON ZPERSON.Z_PK = ZDETECTEDFACE.ZPERSON;
|
||||
JOIN {asset_table} ON {asset_table}.Z_PK = {asset_fk}
|
||||
JOIN ZPERSON ON ZPERSON.Z_PK = {person_fk};
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
62
osxphotos/photosdb/_photosdb_process_shared_library.py
Normal file
62
osxphotos/photosdb/_photosdb_process_shared_library.py
Normal file
@ -0,0 +1,62 @@
|
||||
""" Methods for PhotosDB to process shared iCloud library data (#860)"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from .._constants import _DB_TABLE_NAMES, _PHOTOS_SHARED_LIBRARY_VERSION
|
||||
from ..sqlite_utils import sqlite_open_ro
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from osxphotos.photosdb import PhotosDB
|
||||
|
||||
logger = logging.getLogger("osxphotos")
|
||||
|
||||
|
||||
def _process_shared_library_info(self: PhotosDB):
|
||||
"""Process syndication information"""
|
||||
|
||||
if self.photos_version < 7:
|
||||
raise NotImplementedError(
|
||||
f"syndication info not implemented for this database version: {self.photos_version}"
|
||||
)
|
||||
|
||||
if self._model_ver < _PHOTOS_SHARED_LIBRARY_VERSION:
|
||||
return
|
||||
|
||||
_process_shared_library_info_8(self)
|
||||
|
||||
|
||||
def _process_shared_library_info_8(photosdb: PhotosDB):
|
||||
"""Process shared iCloud library info for Photos 8.0 and later
|
||||
|
||||
Args:
|
||||
photosdb: an OSXPhotosDB instance
|
||||
"""
|
||||
|
||||
db = photosdb._tmp_db
|
||||
zasset = _DB_TABLE_NAMES[photosdb._photos_ver]["ASSET"]
|
||||
|
||||
(conn, cursor) = sqlite_open_ro(db)
|
||||
|
||||
result = cursor.execute(
|
||||
f"""
|
||||
SELECT
|
||||
{zasset}.ZUUID,
|
||||
{zasset}.ZACTIVELIBRARYSCOPEPARTICIPATIONSTATE,
|
||||
{zasset}.ZLIBRARYSCOPESHARESTATE,
|
||||
{zasset}.ZLIBRARYSCOPE
|
||||
FROM {zasset}
|
||||
"""
|
||||
)
|
||||
|
||||
for row in result:
|
||||
uuid = row[0]
|
||||
if uuid not in photosdb._dbphotos:
|
||||
logger.debug(f"Skipping shared library info for missing uuid: {uuid}")
|
||||
continue
|
||||
info = photosdb._dbphotos[uuid]
|
||||
info["active_library_participation_state"] = row[1]
|
||||
info["library_scope_share_state"] = row[2]
|
||||
info["library_scope"] = row[3]
|
||||
@ -4,7 +4,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from .._constants import _DB_TABLE_NAMES
|
||||
from .._constants import _DB_TABLE_NAMES, _PHOTOS_SYNDICATION_MODEL_VERSION
|
||||
from ..sqlite_utils import sqlite_open_ro
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -16,15 +16,18 @@ def _process_syndicationinfo(self: PhotosDB):
|
||||
|
||||
self._db_syndication_uuid = {}
|
||||
|
||||
if self.photos_version < 8:
|
||||
if self.photos_version < 7:
|
||||
raise NotImplementedError(
|
||||
f"syndication info not implemented for this database version: {self.photos_version}"
|
||||
)
|
||||
else:
|
||||
_process_syndicationinfo_8(self)
|
||||
|
||||
if self._model_ver < _PHOTOS_SYNDICATION_MODEL_VERSION:
|
||||
return
|
||||
|
||||
_process_syndicationinfo_7(self)
|
||||
|
||||
|
||||
def _process_syndicationinfo_8(photosdb: PhotosDB):
|
||||
def _process_syndicationinfo_7(photosdb: PhotosDB):
|
||||
"""Process Syndication info for Photos 8.0 and later
|
||||
|
||||
Args:
|
||||
|
||||
@ -62,7 +62,11 @@ from ..rich_utils import add_rich_markup_tag
|
||||
from ..sqlite_utils import sqlite_db_is_locked, sqlite_open_ro
|
||||
from ..unicode import normalize_unicode
|
||||
from ..utils import _check_file_exists, get_last_library_path, noop
|
||||
from .photosdb_utils import get_db_model_version, get_db_version
|
||||
from .photosdb_utils import (
|
||||
get_db_version,
|
||||
get_model_version,
|
||||
get_photos_version_from_model,
|
||||
)
|
||||
|
||||
if is_macos:
|
||||
import photoscript
|
||||
@ -91,6 +95,7 @@ class PhotosDB:
|
||||
labels_normalized,
|
||||
labels_normalized_as_dict,
|
||||
)
|
||||
from ._photosdb_process_shared_library import _process_shared_library_info
|
||||
from ._photosdb_process_syndicationinfo import _process_syndicationinfo
|
||||
|
||||
def __init__(
|
||||
@ -286,7 +291,7 @@ class PhotosDB:
|
||||
# Dict to hold data on imports for Photos <= 4
|
||||
self._db_import_group = {}
|
||||
|
||||
# Dict to hold syndication info for Photos >= 8
|
||||
# Dict to hold syndication info for Photos >= 7
|
||||
# key is UUID and value is dict of syndication info
|
||||
self._db_syndication_uuid = {}
|
||||
|
||||
@ -326,7 +331,7 @@ class PhotosDB:
|
||||
# photoanalysisd sometimes maintains this lock even after Photos is closed
|
||||
# In those cases, make a temp copy of the file for sqlite3 to read
|
||||
if sqlite_db_is_locked(self._dbfile):
|
||||
verbose(f"Database locked, creating temporary copy.")
|
||||
verbose("Database locked, creating temporary copy.")
|
||||
self._tmp_db = self._copy_db_file(self._dbfile)
|
||||
|
||||
# _db_version is set from photos.db
|
||||
@ -341,21 +346,23 @@ class PhotosDB:
|
||||
self._photos_ver = 4
|
||||
else:
|
||||
self._photos_ver = 5
|
||||
self._model_ver = 0 # only set for Photos 5+
|
||||
|
||||
# If Photos >= 5, actual data isn't in photos.db but in Photos.sqlite
|
||||
if int(self._db_version) > int(_PHOTOS_4_VERSION):
|
||||
dbpath = pathlib.Path(self._dbfile).parent
|
||||
dbfile = dbpath / "Photos.sqlite"
|
||||
if not _check_file_exists(dbfile):
|
||||
raise FileNotFoundError(f"dbfile {dbfile} does not exist", dbfile)
|
||||
else:
|
||||
self._dbfile_actual = self._tmp_db = dbfile
|
||||
verbose(f"Processing database {self._filepath(self._dbfile_actual)}")
|
||||
# if database is exclusively locked, make a copy of it and use the copy
|
||||
if sqlite_db_is_locked(self._dbfile_actual):
|
||||
verbose(f"Database locked, creating temporary copy.")
|
||||
self._tmp_db = self._copy_db_file(self._dbfile_actual)
|
||||
self._dbfile_actual = self._tmp_db = dbfile
|
||||
verbose(f"Processing database {self._filepath(self._dbfile_actual)}")
|
||||
# if database is exclusively locked, make a copy of it and use the copy
|
||||
if sqlite_db_is_locked(self._dbfile_actual):
|
||||
verbose("Database locked, creating temporary copy.")
|
||||
self._tmp_db = self._copy_db_file(self._dbfile_actual)
|
||||
# set the photos version to actual value based on Photos.sqlite
|
||||
self._photos_ver = get_db_model_version(self._tmp_db)
|
||||
self._photos_ver = get_photos_version_from_model(self._tmp_db)
|
||||
self._model_ver = get_model_version(self._tmp_db)
|
||||
|
||||
logger.debug(
|
||||
f"_dbfile = {self._dbfile}, _dbfile_actual = {self._dbfile_actual}"
|
||||
@ -1235,6 +1242,9 @@ class PhotosDB:
|
||||
# photos 5+ only, for shared photos
|
||||
self._dbphotos[uuid]["cloudownerhashedpersonid"] = None
|
||||
|
||||
# photos 7+ only, shared moments
|
||||
self._dbphotos[uuid]["moment_share"] = None
|
||||
|
||||
# compute signatures for finding possible duplicates
|
||||
signature = self._duplicate_signature(uuid)
|
||||
try:
|
||||
@ -1547,6 +1557,12 @@ class PhotosDB:
|
||||
info["UTI_raw"] = None
|
||||
info["raw_pair_info"] = None
|
||||
|
||||
# placeholders for shared library info on Photos 8+
|
||||
for uuid in self._dbphotos:
|
||||
self._dbphotos[uuid]["active_library_participation_state"] = None
|
||||
self._dbphotos[uuid]["library_scope_share_state"] = None
|
||||
self._dbphotos[uuid]["library_scope"] = None
|
||||
|
||||
# done with the database connection
|
||||
conn.close()
|
||||
|
||||
@ -1706,6 +1722,7 @@ class PhotosDB:
|
||||
|
||||
# get info on keyface -- some photos have null keyface so can't do a single query
|
||||
# (at least not with my SQL skills)
|
||||
asset_fk = _DB_TABLE_NAMES[photos_ver]["DETECTED_FACE_ASSET_FK"]
|
||||
c.execute(
|
||||
f""" SELECT
|
||||
ZPERSON.Z_PK,
|
||||
@ -1714,7 +1731,7 @@ class PhotosDB:
|
||||
ZDETECTEDFACE.ZUUID
|
||||
FROM ZPERSON, ZDETECTEDFACE, {asset_table}
|
||||
WHERE ZDETECTEDFACE.Z_PK = ZPERSON.ZKEYFACE AND
|
||||
ZDETECTEDFACE.ZASSET = {asset_table}.Z_PK
|
||||
{asset_fk} = {asset_table}.Z_PK
|
||||
"""
|
||||
)
|
||||
|
||||
@ -1733,13 +1750,14 @@ class PhotosDB:
|
||||
|
||||
# get information on detected faces
|
||||
verbose("Processing detected faces in photos.")
|
||||
person_fk = _DB_TABLE_NAMES[photos_ver]["DETECTED_FACE_PERSON_FK"]
|
||||
c.execute(
|
||||
f""" SELECT
|
||||
ZPERSON.Z_PK,
|
||||
{asset_table}.ZUUID
|
||||
FROM ZPERSON, ZDETECTEDFACE, {asset_table}
|
||||
WHERE ZDETECTEDFACE.ZPERSON = ZPERSON.Z_PK AND
|
||||
ZDETECTEDFACE.ZASSET = {asset_table}.Z_PK
|
||||
WHERE {person_fk} = ZPERSON.Z_PK AND
|
||||
{asset_fk} = {asset_table}.Z_PK
|
||||
"""
|
||||
)
|
||||
|
||||
@ -1947,7 +1965,8 @@ class PhotosDB:
|
||||
{asset_table}.ZSAVEDASSETTYPE,
|
||||
{asset_table}.ZADDEDDATE,
|
||||
{asset_table}.Z_PK,
|
||||
{asset_table}.ZCLOUDOWNERHASHEDPERSONID
|
||||
{asset_table}.ZCLOUDOWNERHASHEDPERSONID,
|
||||
{asset_table}.ZMOMENTSHARE
|
||||
FROM {asset_table}
|
||||
JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = {asset_table}.Z_PK
|
||||
ORDER BY {asset_table}.ZUUID """
|
||||
@ -1998,6 +2017,7 @@ class PhotosDB:
|
||||
# 41 ZGENERICASSET.ZADDEDDATE -- date item added to the library
|
||||
# 42 ZGENERICASSET.Z_PK -- primary key
|
||||
# 43 ZGENERICASSET.ZCLOUDOWNERHASHEDPERSONID -- used to look up owner name (for shared photos)
|
||||
# 44 ZASSET.ZMOMENTSHARE -- FK for ZSHARE (shared moments, Photos 5+; in Photos 7+ these are in the scopes/momentshared folder)
|
||||
|
||||
for row in c:
|
||||
uuid = row[0]
|
||||
@ -2185,6 +2205,8 @@ class PhotosDB:
|
||||
info["pk"] = row[42]
|
||||
info["cloudownerhashedpersonid"] = row[43]
|
||||
|
||||
info["moment_share"] = row[44]
|
||||
|
||||
# initialize import session info which will be filled in later
|
||||
# not every photo has an import session so initialize all records now
|
||||
info["import_session"] = None
|
||||
@ -2209,6 +2231,11 @@ class PhotosDB:
|
||||
info["UTI_edited_photo"] = None
|
||||
info["UTI_edited_video"] = None
|
||||
|
||||
# placeholder for shared library info (Photos 8+)
|
||||
info["active_library_participation_state"] = None
|
||||
info["library_scope_share_state"] = None
|
||||
info["library_scope"] = None
|
||||
|
||||
self._dbphotos[uuid] = info
|
||||
|
||||
# compute signatures for finding possible duplicates
|
||||
@ -2517,10 +2544,14 @@ class PhotosDB:
|
||||
verbose("Processing moments.")
|
||||
self._process_moments()
|
||||
|
||||
if self.photos_version >= 8:
|
||||
if self.photos_version >= 7:
|
||||
verbose("Processing syndication info.")
|
||||
self._process_syndicationinfo()
|
||||
|
||||
if self.photos_version >= 8:
|
||||
verbose("Processing shared iCloud library info")
|
||||
self._process_shared_library_info()
|
||||
|
||||
verbose("Done processing details from Photos library.")
|
||||
|
||||
def _process_moments(self):
|
||||
@ -3530,6 +3561,16 @@ class PhotosDB:
|
||||
elif options.not_saved_to_library:
|
||||
photos = [p for p in photos if p.syndicated and not p.saved_to_library]
|
||||
|
||||
if options.shared_moment:
|
||||
photos = [p for p in photos if p.shared_moment]
|
||||
elif options.not_shared_moment:
|
||||
photos = [p for p in photos if not p.shared_moment]
|
||||
|
||||
if options.shared_library:
|
||||
photos = [p for p in photos if p.shared_library]
|
||||
elif options.not_shared_library:
|
||||
photos = [p for p in photos if not p.shared_library]
|
||||
|
||||
if options.function:
|
||||
for function in options.function:
|
||||
photos = function[0](photos)
|
||||
|
||||
@ -16,6 +16,7 @@ from .._constants import (
|
||||
_PHOTOS_6_MODEL_VERSION,
|
||||
_PHOTOS_7_MODEL_VERSION,
|
||||
_PHOTOS_8_MODEL_VERSION,
|
||||
_PHOTOS_9_MODEL_VERSION,
|
||||
_TESTED_DB_VERSIONS,
|
||||
)
|
||||
from ..sqlite_utils import sqlite_open_ro
|
||||
@ -23,7 +24,7 @@ from ..sqlite_utils import sqlite_open_ro
|
||||
__all__ = [
|
||||
"get_db_version",
|
||||
"get_model_version",
|
||||
"get_db_model_version",
|
||||
"get_photos_version_from_model",
|
||||
"get_photos_library_version",
|
||||
]
|
||||
|
||||
@ -93,7 +94,7 @@ def get_model_version(db_file: str) -> str:
|
||||
return plist["PLModelVersion"]
|
||||
|
||||
|
||||
def get_db_model_version(db_file: str) -> int:
|
||||
def get_photos_version_from_model(db_file: str) -> int:
|
||||
"""Returns Photos version based on model version found in db_file
|
||||
|
||||
Args:
|
||||
@ -112,10 +113,12 @@ def get_db_model_version(db_file: str) -> int:
|
||||
return 7
|
||||
elif _PHOTOS_8_MODEL_VERSION[0] <= model_ver <= _PHOTOS_8_MODEL_VERSION[1]:
|
||||
return 8
|
||||
elif _PHOTOS_9_MODEL_VERSION[0] <= model_ver <= _PHOTOS_9_MODEL_VERSION[1]:
|
||||
return 9
|
||||
else:
|
||||
logging.warning(f"Unknown model version: {model_ver}")
|
||||
# cross our fingers and try latest version
|
||||
return 8
|
||||
return 9
|
||||
|
||||
|
||||
def get_photos_library_version(library_path: str | pathlib.Path) -> int:
|
||||
@ -149,10 +152,12 @@ def get_photos_library_version(library_path: str | pathlib.Path) -> int:
|
||||
return 7
|
||||
if _PHOTOS_8_MODEL_VERSION[0] <= model_ver <= _PHOTOS_8_MODEL_VERSION[1]:
|
||||
return 8
|
||||
if _PHOTOS_9_MODEL_VERSION[0] <= model_ver <= _PHOTOS_9_MODEL_VERSION[1]:
|
||||
return 9
|
||||
logging.warning(
|
||||
f"Unknown db / model version: db_ver={db_ver}, model_ver={model_ver}; assuming Photos 8"
|
||||
)
|
||||
return 8
|
||||
return 9
|
||||
|
||||
|
||||
def get_db_path_for_library(photos_library: str | pathlib.Path) -> pathlib.Path:
|
||||
|
||||
@ -204,10 +204,12 @@ class PersonTable(Table):
|
||||
def rows(self) -> list[tuple[Any]]:
|
||||
"""Return rows for this photo from the ZPERSON table."""
|
||||
conn, cursor = self.db.get_db_connection()
|
||||
person_fk = _DB_TABLE_NAMES[self.version]["DETECTED_FACE_PERSON_FK"]
|
||||
asset_fk = _DB_TABLE_NAMES[self.version]["DETECTED_FACE_ASSET_FK"]
|
||||
sql = f""" SELECT ZPERSON.*
|
||||
FROM ZPERSON
|
||||
JOIN ZDETECTEDFACE ON ZDETECTEDFACE.ZPERSON = ZPERSON.Z_PK
|
||||
JOIN ZASSET ON ZASSET.Z_PK = ZDETECTEDFACE.ZASSET
|
||||
JOIN ZDETECTEDFACE ON {person_fk} = ZPERSON.Z_PK
|
||||
JOIN ZASSET ON ZASSET.Z_PK = {asset_fk}
|
||||
WHERE {self.asset_table}.ZUUID = ?;
|
||||
"""
|
||||
cursor.execute(sql, (self.uuid,))
|
||||
@ -216,10 +218,12 @@ class PersonTable(Table):
|
||||
def _get_column(self, column: str) -> tuple[Any]:
|
||||
"""Get column value for this photo from the ZPERSON table."""
|
||||
conn, cursor = self.db.get_db_connection()
|
||||
person_fk = _DB_TABLE_NAMES[self.version]["DETECTED_FACE_PERSON_FK"]
|
||||
asset_fk = _DB_TABLE_NAMES[self.version]["DETECTED_FACE_ASSET_FK"]
|
||||
sql = f""" SELECT ZPERSON.{column}
|
||||
FROM ZPERSON
|
||||
JOIN ZDETECTEDFACE ON ZDETECTEDFACE.ZPERSON = ZPERSON.Z_PK
|
||||
JOIN ZASSET ON ZASSET.Z_PK = ZDETECTEDFACE.ZASSET
|
||||
JOIN ZDETECTEDFACE ON {person_fk} = ZPERSON.Z_PK
|
||||
JOIN ZASSET ON ZASSET.Z_PK = {asset_fk}
|
||||
WHERE {self.asset_table}.ZUUID = ?;
|
||||
"""
|
||||
cursor.execute(sql, (self.uuid,))
|
||||
|
||||
@ -130,9 +130,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:
|
||||
|
||||
|
||||
@ -149,9 +149,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:
|
||||
|
||||
|
||||
@ -464,7 +464,7 @@ class PhotoTemplate:
|
||||
([rendered_strings], [unmatched]): tuple of list of rendered strings and list of unmatched template values
|
||||
"""
|
||||
|
||||
if type(template) is not str:
|
||||
if not isinstance(template, str):
|
||||
raise TypeError(f"template must be type str, not {type(template)}")
|
||||
|
||||
self.options = options
|
||||
@ -1395,7 +1395,7 @@ class PhotoTemplate:
|
||||
# if no uuid, then template is being validated but not actually run
|
||||
# so don't run the function
|
||||
values = []
|
||||
elif caller in ["export", "query"]:
|
||||
elif caller in {"export", "query"}:
|
||||
# function signature is:
|
||||
# def example(photo: PhotoInfo, options: ExportOptions, args: Optional[str] = None, **kwargs) -> Union[List, str]:
|
||||
values = template_func(self.photo, options=self.options, args=field_arg)
|
||||
@ -1411,7 +1411,7 @@ class PhotoTemplate:
|
||||
raise TypeError(
|
||||
f"Invalid return type for function {funcname}: expected str or list"
|
||||
)
|
||||
if type(values) == str:
|
||||
if isinstance(values, str):
|
||||
values = [values]
|
||||
|
||||
# sanitize directory names if needed
|
||||
|
||||
@ -112,6 +112,10 @@ class QueryOptions:
|
||||
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 been saved to the Photos library
|
||||
not_saved_to_library: search for syndicated photos that have not been saved to the Photos library
|
||||
shared_moment: search for photos that have been shared via a shared moment
|
||||
not_shared_moment: search for photos that have not been shared via a shared moment
|
||||
shared_library: search for photos that are part of a shared iCloud library
|
||||
not_shared_library: search for photos that are not part of a shared iCloud library
|
||||
"""
|
||||
|
||||
added_after: Optional[datetime.datetime] = None
|
||||
@ -200,6 +204,10 @@ class QueryOptions:
|
||||
not_syndicated: Optional[bool] = None
|
||||
saved_to_library: Optional[bool] = None
|
||||
not_saved_to_library: Optional[bool] = None
|
||||
shared_moment: Optional[bool] = None
|
||||
not_shared_moment: Optional[bool] = None
|
||||
shared_library: Optional[bool] = None
|
||||
not_shared_library: Optional[bool] = None
|
||||
|
||||
def asdict(self):
|
||||
return asdict(self)
|
||||
@ -271,7 +279,10 @@ def query_options_from_kwargs(**kwargs) -> QueryOptions:
|
||||
("deleted_only", "not_deleted"),
|
||||
("syndicated", "not_syndicated"),
|
||||
("saved_to_library", "not_saved_to_library"),
|
||||
("shared_moment", "not_shared_moment"),
|
||||
("shared_library", "not_shared_library"),
|
||||
]
|
||||
|
||||
# TODO: add option to validate requiring at least one query arg
|
||||
for arg, not_arg in exclusive:
|
||||
if kwargs.get(arg) and kwargs.get(not_arg):
|
||||
|
||||
200
osxphotos/shareinfo.py
Normal file
200
osxphotos/shareinfo.py
Normal file
@ -0,0 +1,200 @@
|
||||
"""Info about shared photos"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import datetime
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ._constants import TIME_DELTA
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .photosdb import PhotosDB
|
||||
|
||||
|
||||
@dataclass
|
||||
class ShareInfo:
|
||||
"""Info about a share"""
|
||||
|
||||
_pk: int | None
|
||||
cloud_delete_state: int | None
|
||||
local_publish_state: int | None
|
||||
public_permission: int | None
|
||||
scope_type: int | None
|
||||
status: int | None
|
||||
trashed_state: int | None
|
||||
auto_share_policy: int | None
|
||||
cloud_item_count: int | None
|
||||
cloud_local_state: int | None
|
||||
cloud_photo_count: int | None
|
||||
cloud_video_count: int | None
|
||||
exit_state: int | None
|
||||
participant_cloud_update_state: int | None
|
||||
preview_state: int | None
|
||||
scope_syncing_state: int | None
|
||||
asset_count: int | None
|
||||
force_sync_attempted: int | None
|
||||
photos_count: int | None
|
||||
should_ignore_budgets: int | None
|
||||
should_notify_on_upload_completion: int | None
|
||||
uploaded_photos_count: int | None
|
||||
uploaded_videos_count: int | None
|
||||
videos_count: int | None
|
||||
creation_date: datetime.datetime | None
|
||||
expiry_date: datetime.datetime | None
|
||||
trashed_date: datetime.datetime | None
|
||||
last_participant_asset_trash_notification_date: datetime.datetime | None
|
||||
last_participant_asset_trash_notification_viewed_date: datetime.datetime | None
|
||||
end_date: datetime.datetime | None
|
||||
start_date: datetime.datetime | None
|
||||
scope_identifier: str | None
|
||||
title: str | None
|
||||
uuid: str | None
|
||||
originating_scope_identifier: str | None
|
||||
share_url: str | None
|
||||
rules_data: bytes | None
|
||||
preview_data: bytes | None
|
||||
thumbnail_image_data: bytes | None
|
||||
exit_source: int | None
|
||||
count_of_assets_added_by_camera_smart_sharing: int | None
|
||||
exit_type: int | None
|
||||
|
||||
def __post_init__(self):
|
||||
"""Convert dates from str to datetime"""
|
||||
for field in [
|
||||
"creation_date",
|
||||
"expiry_date",
|
||||
"trashed_date",
|
||||
"last_participant_asset_trash_notification_date",
|
||||
"last_participant_asset_trash_notification_viewed_date",
|
||||
"end_date",
|
||||
"start_date",
|
||||
]:
|
||||
if val := getattr(self, field):
|
||||
setattr(self, field, datetime.datetime.fromtimestamp(val + TIME_DELTA))
|
||||
|
||||
def asdict(self):
|
||||
"""Return info as dict"""
|
||||
return dataclasses.asdict(self)
|
||||
|
||||
|
||||
def get_moment_share_info(db: PhotosDB, uuid: str | None) -> ShareInfo:
|
||||
"""Get info about a moment share"""
|
||||
|
||||
sql = """ SELECT
|
||||
ZSHARE.Z_PK,
|
||||
ZSHARE.ZCLOUDDELETESTATE,
|
||||
ZSHARE.ZLOCALPUBLISHSTATE,
|
||||
ZSHARE.ZPUBLICPERMISSION,
|
||||
ZSHARE.ZSCOPETYPE,
|
||||
ZSHARE.ZSTATUS,
|
||||
ZSHARE.ZTRASHEDSTATE,
|
||||
ZSHARE.ZAUTOSHAREPOLICY,
|
||||
ZSHARE.ZCLOUDITEMCOUNT,
|
||||
ZSHARE.ZCLOUDLOCALSTATE,
|
||||
ZSHARE.ZCLOUDPHOTOCOUNT,
|
||||
ZSHARE.ZCLOUDVIDEOCOUNT,
|
||||
ZSHARE.ZEXITSTATE,
|
||||
ZSHARE.ZPARTICIPANTCLOUDUPDATESTATE,
|
||||
ZSHARE.ZPREVIEWSTATE,
|
||||
ZSHARE.ZSCOPESYNCINGSTATE,
|
||||
ZSHARE.ZASSETCOUNT,
|
||||
ZSHARE.ZFORCESYNCATTEMPTED,
|
||||
ZSHARE.ZPHOTOSCOUNT,
|
||||
ZSHARE.ZSHOULDIGNOREBUDGETS,
|
||||
ZSHARE.ZSHOULDNOTIFYONUPLOADCOMPLETION,
|
||||
ZSHARE.ZUPLOADEDPHOTOSCOUNT,
|
||||
ZSHARE.ZUPLOADEDVIDEOSCOUNT,
|
||||
ZSHARE.ZVIDEOSCOUNT,
|
||||
ZSHARE.ZCREATIONDATE,
|
||||
ZSHARE.ZEXPIRYDATE,
|
||||
ZSHARE.ZTRASHEDDATE,
|
||||
ZSHARE.ZLASTPARTICIPANTASSETTRASHNOTIFICATIONDATE,
|
||||
ZSHARE.ZLASTPARTICIPANTASSETTRASHNOTIFICATIONVIEWEDDATE,
|
||||
ZSHARE.ZENDDATE,
|
||||
ZSHARE.ZSTARTDATE,
|
||||
ZSHARE.ZSCOPEIDENTIFIER,
|
||||
ZSHARE.ZTITLE,
|
||||
ZSHARE.ZUUID,
|
||||
ZSHARE.ZORIGINATINGSCOPEIDENTIFIER,
|
||||
ZSHARE.ZSHAREURL,
|
||||
ZSHARE.ZRULESDATA,
|
||||
ZSHARE.ZPREVIEWDATA,
|
||||
ZSHARE.ZTHUMBNAILIMAGEDATA,
|
||||
ZSHARE.ZEXITSOURCE,
|
||||
ZSHARE.ZCOUNTOFASSETSADDEDBYCAMERASMARTSHARING,
|
||||
ZSHARE.ZEXITTYPE
|
||||
FROM ZSHARE
|
||||
JOIN ZASSET ON ZASSET.ZMOMENTSHARE = ZSHARE.Z_PK
|
||||
WHERE ZASSET.ZUUID = '{}'
|
||||
;"""
|
||||
sql = sql.format(uuid)
|
||||
|
||||
if row := db.execute(sql).fetchone():
|
||||
return ShareInfo(*row)
|
||||
raise ValueError(f"Could not find share for uuid {uuid}")
|
||||
|
||||
|
||||
def get_share_info(db: PhotosDB, uuid: str | None) -> ShareInfo:
|
||||
"""Get info about a moment share"""
|
||||
|
||||
# TODO: this is a total guess right now. I think that ZSHARE holds information
|
||||
# about both shared moments and shared iCloud Library
|
||||
# The foreign key for shared moments appears to be ZASSET.ZMOMENTSHARE
|
||||
# but I don't know the key for shared iCloud Libraries
|
||||
# I'm guessing it's ZASSET.ZSHARESCOPE but I don't know for sure and will need
|
||||
# to test on a library that has shared iCloud Library and shared moments
|
||||
|
||||
sql = """ SELECT
|
||||
ZSHARE.Z_PK,
|
||||
ZSHARE.ZCLOUDDELETESTATE,
|
||||
ZSHARE.ZLOCALPUBLISHSTATE,
|
||||
ZSHARE.ZPUBLICPERMISSION,
|
||||
ZSHARE.ZSCOPETYPE,
|
||||
ZSHARE.ZSTATUS,
|
||||
ZSHARE.ZTRASHEDSTATE,
|
||||
ZSHARE.ZAUTOSHAREPOLICY,
|
||||
ZSHARE.ZCLOUDITEMCOUNT,
|
||||
ZSHARE.ZCLOUDLOCALSTATE,
|
||||
ZSHARE.ZCLOUDPHOTOCOUNT,
|
||||
ZSHARE.ZCLOUDVIDEOCOUNT,
|
||||
ZSHARE.ZEXITSTATE,
|
||||
ZSHARE.ZPARTICIPANTCLOUDUPDATESTATE,
|
||||
ZSHARE.ZPREVIEWSTATE,
|
||||
ZSHARE.ZSCOPESYNCINGSTATE,
|
||||
ZSHARE.ZASSETCOUNT,
|
||||
ZSHARE.ZFORCESYNCATTEMPTED,
|
||||
ZSHARE.ZPHOTOSCOUNT,
|
||||
ZSHARE.ZSHOULDIGNOREBUDGETS,
|
||||
ZSHARE.ZSHOULDNOTIFYONUPLOADCOMPLETION,
|
||||
ZSHARE.ZUPLOADEDPHOTOSCOUNT,
|
||||
ZSHARE.ZUPLOADEDVIDEOSCOUNT,
|
||||
ZSHARE.ZVIDEOSCOUNT,
|
||||
ZSHARE.ZCREATIONDATE,
|
||||
ZSHARE.ZEXPIRYDATE,
|
||||
ZSHARE.ZTRASHEDDATE,
|
||||
ZSHARE.ZLASTPARTICIPANTASSETTRASHNOTIFICATIONDATE,
|
||||
ZSHARE.ZLASTPARTICIPANTASSETTRASHNOTIFICATIONVIEWEDDATE,
|
||||
ZSHARE.ZENDDATE,
|
||||
ZSHARE.ZSTARTDATE,
|
||||
ZSHARE.ZSCOPEIDENTIFIER,
|
||||
ZSHARE.ZTITLE,
|
||||
ZSHARE.ZUUID,
|
||||
ZSHARE.ZORIGINATINGSCOPEIDENTIFIER,
|
||||
ZSHARE.ZSHAREURL,
|
||||
ZSHARE.ZRULESDATA,
|
||||
ZSHARE.ZPREVIEWDATA,
|
||||
ZSHARE.ZTHUMBNAILIMAGEDATA,
|
||||
ZSHARE.ZEXITSOURCE,
|
||||
ZSHARE.ZCOUNTOFASSETSADDEDBYCAMERASMARTSHARING,
|
||||
ZSHARE.ZEXITTYPE
|
||||
FROM ZSHARE
|
||||
JOIN ZASSET ON ZASSET.ZLIBRARYSCOPE = ZSHARE.Z_PK
|
||||
WHERE ZASSET.ZUUID = '{}'
|
||||
;"""
|
||||
sql = sql.format(uuid)
|
||||
|
||||
if row := db.execute(sql).fetchone():
|
||||
return ShareInfo(*row)
|
||||
raise ValueError(f"Could not find share for uuid {uuid}")
|
||||
63
osxphotos/shareparticipant.py
Normal file
63
osxphotos/shareparticipant.py
Normal file
@ -0,0 +1,63 @@
|
||||
"""Information about share participants for shared photos"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .photosdb import PhotosDB
|
||||
|
||||
|
||||
def get_share_participants(db: PhotosDB, uuid: str) -> list[ShareParticipant]:
|
||||
"""Return list of ShareParticipant objects for the given database"""
|
||||
sql = """ SELECT
|
||||
ZSHAREPARTICIPANT.Z_PK,
|
||||
ZSHAREPARTICIPANT.ZACCEPTANCESTATUS,
|
||||
ZSHAREPARTICIPANT.ZISCURRENTUSER,
|
||||
ZSHAREPARTICIPANT.ZEXITSTATE,
|
||||
ZSHAREPARTICIPANT.ZPERMISSION,
|
||||
ZSHAREPARTICIPANT.ZPERSON,
|
||||
ZSHAREPARTICIPANT.Z54_SHARE,
|
||||
ZSHAREPARTICIPANT.ZSHARE,
|
||||
ZSHAREPARTICIPANT.ZEMAILADDRESS,
|
||||
ZSHAREPARTICIPANT.ZPARTICIPANTID,
|
||||
ZSHAREPARTICIPANT.ZPHONENUMBER,
|
||||
ZSHAREPARTICIPANT.ZUSERIDENTIFIER,
|
||||
ZSHAREPARTICIPANT.ZUUID,
|
||||
ZSHAREPARTICIPANT.ZNAMECOMPONENTS
|
||||
FROM ZSHAREPARTICIPANT
|
||||
JOIN ZASSETCONTRIBUTOR ON ZSHAREPARTICIPANT.Z_PK = ZASSETCONTRIBUTOR.ZPARTICIPANT
|
||||
JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.Z_PK = ZASSETCONTRIBUTOR.Z3LIBRARYSCOPEASSETCONTRIBUTORS
|
||||
JOIN ZASSET ON ZASSET.Z_PK = ZADDITIONALASSETATTRIBUTES.ZASSET
|
||||
WHERE ZASSET.ZUUID = '{}';""".format(
|
||||
uuid
|
||||
)
|
||||
|
||||
rows = db.execute(sql)
|
||||
return [ShareParticipant(*row) for row in rows]
|
||||
|
||||
|
||||
@dataclass
|
||||
class ShareParticipant:
|
||||
"""Information about a share participant"""
|
||||
|
||||
_pk: int
|
||||
_acceptance_status: int
|
||||
is_current_user: bool
|
||||
_exit_state: int
|
||||
_permission: int
|
||||
_person: int
|
||||
_z54_share: int
|
||||
_share: int
|
||||
email_address: str
|
||||
participant_id: str
|
||||
phone_number: str
|
||||
user_identifier: str
|
||||
uuid: str
|
||||
_name_components: bytes
|
||||
|
||||
def asdict(self):
|
||||
"""Return share participant as a dict"""
|
||||
return dataclasses.asdict(self)
|
||||
@ -40,7 +40,7 @@ def sqlgrep(
|
||||
for row_num, row in enumerate(cursor):
|
||||
for field in row.keys():
|
||||
field_value = row[field]
|
||||
if not field_value or type(field_value) == bytes:
|
||||
if not field_value or isinstance(field_value, bytes):
|
||||
# don't search binary blobs
|
||||
next
|
||||
field_value = str(field_value)
|
||||
|
||||
@ -253,8 +253,6 @@ def list_photo_libraries():
|
||||
return lib_list
|
||||
|
||||
|
||||
|
||||
|
||||
# def findfiles(pattern, path):
|
||||
# """Returns list of filenames from path matched by pattern
|
||||
# shell pattern. Matching is case-insensitive.
|
||||
|
||||
18
pyproject.toml
Normal file
18
pyproject.toml
Normal file
@ -0,0 +1,18 @@
|
||||
[tool.ruff]
|
||||
# Docs: https://beta.ruff.rs/docs/
|
||||
# Rules: https://beta.ruff.rs/docs/rules/
|
||||
target-version = "py39"
|
||||
line-length = 366
|
||||
ignore = ["E402","E722","E741","F401","F403","F405","F541","F822","F841"]
|
||||
# Exclude a variety of commonly ignored directories.
|
||||
exclude = [
|
||||
".git",
|
||||
".mypy_cache",
|
||||
".pre-commit-cache",
|
||||
".ruff_cache",
|
||||
".tox",
|
||||
".venv",
|
||||
"venv",
|
||||
"docs",
|
||||
"__pycache",
|
||||
]
|
||||
12
sweep.yaml
Normal file
12
sweep.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
# Sweep AI turns bug fixes & feature requests into code changes (https://sweep.dev)
|
||||
# For details on our config file, check out our docs at https://docs.sweep.dev
|
||||
|
||||
# If you use this be sure to frequently sync your default branch(main, master) to dev.
|
||||
branch: 'main'
|
||||
# By default Sweep will read the logs and outputs from your existing Github Actions. To disable this, set this to false.
|
||||
gha_enabled: True
|
||||
# This is the description of your project. It will be used by sweep when creating PRs. You can tell Sweep what's unique about your project, what frameworks you use, or anything else you want.
|
||||
# Here's an example: sweepai/sweep is a python project. The main api endpoints are in sweepai/api.py. Write code that adheres to PEP8.
|
||||
description: ''
|
||||
|
||||
# Default Values: https://github.com/sweepai/sweep/blob/main/sweep.yaml
|
||||
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>LibrarySchemaVersion</key>
|
||||
<integer>5001</integer>
|
||||
<key>MetaSchemaVersion</key>
|
||||
<integer>3</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
tests/Test-14.0.0.photoslibrary/database/Photos.sqlite
Normal file
BIN
tests/Test-14.0.0.photoslibrary/database/Photos.sqlite
Normal file
Binary file not shown.
BIN
tests/Test-14.0.0.photoslibrary/database/Photos.sqlite-shm
Normal file
BIN
tests/Test-14.0.0.photoslibrary/database/Photos.sqlite-shm
Normal file
Binary file not shown.
BIN
tests/Test-14.0.0.photoslibrary/database/Photos.sqlite-wal
Normal file
BIN
tests/Test-14.0.0.photoslibrary/database/Photos.sqlite-wal
Normal file
Binary file not shown.
16
tests/Test-14.0.0.photoslibrary/database/Photos.sqlite.lock
Normal file
16
tests/Test-14.0.0.photoslibrary/database/Photos.sqlite.lock
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>hostname</key>
|
||||
<string>rhets-Virtual-Machine.local</string>
|
||||
<key>hostuuid</key>
|
||||
<string>DB248ADD-817E-5469-8229-D55158E1D479</string>
|
||||
<key>pid</key>
|
||||
<integer>627</integer>
|
||||
<key>processname</key>
|
||||
<string>photolibraryd</string>
|
||||
<key>uid</key>
|
||||
<integer>501</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
tests/Test-14.0.0.photoslibrary/database/metaSchema.db
Normal file
BIN
tests/Test-14.0.0.photoslibrary/database/metaSchema.db
Normal file
Binary file not shown.
BIN
tests/Test-14.0.0.photoslibrary/database/photos.db
Normal file
BIN
tests/Test-14.0.0.photoslibrary/database/photos.db
Normal file
Binary file not shown.
0
tests/Test-14.0.0.photoslibrary/database/protection
Normal file
0
tests/Test-14.0.0.photoslibrary/database/protection
Normal file
Binary file not shown.
BIN
tests/Test-14.0.0.photoslibrary/database/search/psi.sqlite
Normal file
BIN
tests/Test-14.0.0.photoslibrary/database/search/psi.sqlite
Normal file
Binary file not shown.
BIN
tests/Test-14.0.0.photoslibrary/database/search/psi.sqlite-shm
Normal file
BIN
tests/Test-14.0.0.photoslibrary/database/search/psi.sqlite-shm
Normal file
Binary file not shown.
BIN
tests/Test-14.0.0.photoslibrary/database/search/psi.sqlite-wal
Normal file
BIN
tests/Test-14.0.0.photoslibrary/database/search/psi.sqlite-wal
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user