Updated Structure of the code (markdown)

Rhet Turnbull
2020-05-09 14:21:55 -05:00
parent e24e9fc40f
commit 53119f5689

@@ -1,5 +1,6 @@
osxphotos is built around a set of classes that each handle a particular aspect of the Photos library: 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. * 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. * PhotoInfo: represents an individual photo in the library and all associated metadata.
* AlbumInfo: represents an album in the library. * AlbumInfo: represents an album in the library.
@@ -9,6 +10,7 @@ osxphotos is built around a set of classes that each handle a particular aspect
The package code is organized in osxphotos per the table below. Most of the files contain doc strings describing what they contain. 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| |file|description|
|---|---| |---|---|
|`__init__.py`| this is what gets read by "import osxphotos"| |`__init__.py`| this is what gets read by "import osxphotos"|
@@ -27,7 +29,7 @@ The package code is organized in osxphotos per the table below. Most of the file
|`templates/xmp_sidecar.mako`|mako template used to create [XMP](https://en.wikipedia.org/wiki/Extensible_Metadata_Platform) sidecar files| |`templates/xmp_sidecar.mako`|mako template used to create [XMP](https://en.wikipedia.org/wiki/Extensible_Metadata_Platform) sidecar files|
|`utils.py`| various utility methods--this file is getting bloated and needs to be refactored| |`utils.py`| various utility methods--this file is getting bloated and needs to be refactored|
## How osxphotos works
Broadly, osxphotos works like this: Broadly, osxphotos works like this:
1. Opens a readonly copy of `photos.db`. If the file is locked, a temporary copy will be created then opened. 1. Opens a readonly copy of `photos.db`. If the file is locked, a temporary copy will be created then opened.
2. Reads `photos.db` to determine which version of Photos created the library (`PhotosDB._get_db_version()`) 2. Reads `photos.db` to determine which version of Photos created the library (`PhotosDB._get_db_version()`)
@@ -36,3 +38,11 @@ Broadly, osxphotos works like this:
5. `_process_database4` and `_process_database5` execute several SQL queries to extract the required data. These methods populate a series of data structures in `PhotosDB` which are then used by the rest of code to create the `PhotoInfo`, `AlbumInfo`, and `FolderInfo` objects. These database structures are ugly...in general, they flatten the SQL database into several different python dicts. The "master" dict is called `_dbphotos`. The key is the [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) of the photo and the value is another dict containing details about the photo. Read the code for `PhotosDB.__init__()` for additional details. Each of the data structures is documented in the code. 5. `_process_database4` and `_process_database5` execute several SQL queries to extract the required data. These methods populate a series of data structures in `PhotosDB` which are then used by the rest of code to create the `PhotoInfo`, `AlbumInfo`, and `FolderInfo` objects. These database structures are ugly...in general, they flatten the SQL database into several different python dicts. The "master" dict is called `_dbphotos`. The key is the [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) of the photo and the value is another dict containing details about the photo. Read the code for `PhotosDB.__init__()` for additional details. Each of the data structures is documented in the code.
6. The `PhotoInfo`, `AlbumInfo`, and `FolderInfo` objects are created as needed. For example, `PhotosDB.photos()` returns a list of `PhotoInfo` objects representing the photos in the database and `PhotoInfo.album_info` returns a list of `AlbumInfo` objects representing the albums the photo is contained in. 6. The `PhotoInfo`, `AlbumInfo`, and `FolderInfo` objects are created as needed. For example, `PhotosDB.photos()` returns a list of `PhotoInfo` objects representing the photos in the database and `PhotoInfo.album_info` returns a list of `AlbumInfo` objects 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:
1. Reverse engineer Photos.sqlite and develop an sql query that extracts the data
2. Add this query to `PhotosDB._process_database5` (assuming a Photos 5 library) and store the data in appropriate data structure accessible through `_dbphotos`
3. Add a property to `PhotoInfo` which accesses `_dbphotos` through `self._db` which points to the PhotosDB object
4. If exposing the property to the templating system (`PhotoInfo.render_template()`) and add it to `templates.py` (which is relatively self-documenting)
5. If exposing the property to the command line interface, add it to `__main__.py`