Page:
Structure of the code
Pages
Changes in Photos 6 Big Sur
Database changes from 16.0 to 16.0.1
Developer Tools
Home
Logs of shared images
Machine Learning Photo Classification in Photos 5
Motivation for this project
Photos 4 database schema
Photos 5 database schema
Photos 6 database schema (Big Sur)
Photos 6 to Photos 7 Diff (Big Sur to Monterey 12.0.1)
Photos 7 (Monterey) Schema
Photos 7 to Photos 8 (Monterey to Ventura developer preview) Diff
Photos 7 to Photos 8 diff
Photos 8 Ventura 13.0 dev preview to Ventura 13.0.0 release diff
Photos 8 schema (Ventura MacOS 13.0 developer preview)
Photos 8 schema (Ventura MacOS 13.0.0)
Photos 8 to Photos 9 schema diff (Ventura to Sonoma)
Photos 9 (Sonoma) schema
Photos Behavior
Photos search data (psi.sqlite) diff Monterey to Ventura
Photos version 4 database
Photos version 5 database
Related projects
Schema changes from Photos 2 to Photos 3
Schema changes from Photos 3 to Photos 4
Schema changes from Photos 5 to Photos 6
Setting up a new development environment
Steps to create sql diff of two database versions
Structure of the code
Understanding the Photos database
iPhoto DataModelVersion.plist format
iPhoto database schema
psi.sqlite (search database) changes from Photos 5 to Photos 6
psi.sqlite schema (Photos 5)
psi.sqlite schema (Photos 6)
psi.sqlite schema (Photos 7, Monterey, macOS 12.0.1)
psi.sqlite schema (Photos 8, Ventura, macOS 13.0)
Clone
22
Structure of the code
Rhet Turnbull edited this page 2022-01-02 09:19:26 -08:00
Table of Contents
osxphotos is built around a set of classes that each handle a particular aspect of the Photos library:
osxphotos classes
- PhotosDB: reads the Photos library database and extract all relevant metadata about each photo. This is starting point for any use of osxphotos.
- PhotoInfo: represents an individual photo in the library and all associated metadata.
- AlbumInfo: represents an album in the library.
- FolderInfo: represents a folder in the library.
- PlaceInfo: represents the reverse geolocation info (e.g. the address or place name) associated with a photo.
- ExifTool: provides an interface to the exiftool tool for manipulating EXIF information associated with a photo.
- PhotoTemplate: helper class for rendering a template string.
The package code is organized in osxphotos per the table below. Most of the files contain doc strings describing what they contain.
Source files
| file | description |
|---|---|
__init__.py |
this is what gets read by "import osxphotos" |
__main__.py |
the command line interface, what gets executed with python3 -m osxphotos |
_constants.py |
constants used by the other modules |
_version.py |
version string |
albuminfo.py |
AlbumInfo and FolderInfo classes |
configoptions.py |
ConfigOptions class to load/save config settings for osxphotos CLI |
datetime_formatter.py |
Utility functions for formatting datetime objects, used by phototemplate.py |
datetime_utils.py |
Utility functions for working with datetime objects |
exiftool.py |
ExifTool class |
export_db.py |
ExportDB class used by CLI to cache data about exports |
fileutil.py |
FileUtil class used by CLI and export for enabling --dry-run option |
imageconverter.py |
ImageConverter class that converts an image to JPEG using CoreImage |
pathutils.py |
Utility functions for validating/sanitizing path components |
photokit.py |
Interface to Apple's PhotoKit framework for direct access to photos stored in the user's Photos library. |
photoinfo.py |
PhotoInfo class |
photosdb/ |
PhotosDB class |
phototemplate.py |
PhotoTemplate class |
placeinfo.py |
PlaceInfo class |
templates |
contains mako templates for sidecar export (though the name is similar, these templates are not associated with phototemplate.py |
templates/xmp_sidecar.mako |
mako template used to create XMP sidecar files |
utils.py |
various utility methods--this file is getting bloated and needs to be refactored |
How osxphotos works
Broadly, osxphotos works like this:
- Opens a readonly copy of
photos.db. If the file is locked, a temporary copy will be created then opened. - Reads
photos.dbto determine which version of Photos created the library (PhotosDB._get_db_version()) - If library created with Photos version 2, 3, or 4,
PhotosDB._process_database4()processes the database file to extract all required information. - If library created with Photos 5, the actual database is
Photos.sqliteso this is opened readonly or copied to a temporary file if locked, thenPhotosDB._process_database5()is called to process the database file and extra all required information. _process_database4and_process_database5execute several SQL queries to extract the required data. These methods populate a series of data structures inPhotosDBwhich are then used by the rest of code to create thePhotoInfo,AlbumInfo, andFolderInfoobjects. These database structures are ugly...in general, they flatten the SQL database into several different python dicts. The "main" dict is called_dbphotos. The key is the UUID of the photo and the value is another dict containing details about the photo. Read the code forPhotosDB.__init__()for additional details. Each of the data structures is documented in the code.- The
PhotoInfo,AlbumInfo, andFolderInfoobjects are created as needed. For example,PhotosDB.photos()returns a list ofPhotoInfoobjects representing the photos in the database andPhotoInfo.album_inforeturns a list ofAlbumInfoobjects representing the albums the photo is contained in.
Modifying the code
As an example, here's a rough outline of what you'd need to do to add support for a new metadata attribute:
- Reverse engineer Photos.sqlite and develop an sql query that extracts the data
- Add this query to
PhotosDB._process_database5(assuming a Photos 5 library) and store the data in appropriate data structure accessible through_dbphotos - Add a property to
PhotoInfowhich accesses_dbphotosthroughself._dbwhich points to the PhotosDB object. If your change requires significant code, consider creating a separate file for the method -- see _photoinfo_export.py for an example - If exposing the property to the templating system (
PhotoTemplateandPhotoInfo.render_template()) add it tophototemplate.py(which is relatively self-documenting) - If exposing the property to the command line interface, add it to
__main__.py-- you'll want to look atquery_options,_query(),export(), andexport_photo()at a minimum to ensure the command line tool can access your new attribute. - Add at least one test to
tests/! - Ensure all tests pass
python3 -m pytest tests/ - Format code with black
- Submit a pull request :-)