Added shallow json() option, #1038 (#1040)

This commit is contained in:
Rhet Turnbull 2023-04-08 11:10:29 -07:00 committed by GitHub
parent f4a743468d
commit d2b7783125
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 91 additions and 30 deletions

View File

@ -1212,7 +1212,7 @@ class PhotoExporter:
# set data in the database
with export_db.create_or_get_file_record(dest_str, self.photo.uuid) as rec:
rec.photoinfo = self.photo.json()
rec.photoinfo = self.photo.json(shallow=True)
rec.export_options = options.bit_flags
# don't set src_sig as that is set above before any modifications by convert_to_jpeg or exiftool
if not options.ignore_signature:

View File

@ -1888,14 +1888,46 @@ class PhotoInfo:
"width": self.width,
}
def json(self):
"""Return JSON representation"""
def json(self, indent: int | None = None, shallow: bool = False) -> str:
"""Return JSON representation
Args:
indent: indent level for JSON, if None, no indent
shallow: if True, return shallow JSON representation (does not contain folder_info, person_info, etc.)
Returns:
JSON string
"""
def default(o):
if isinstance(o, (datetime.date, datetime.datetime)):
return o.isoformat()
dict_data = self.asdict()
if shallow:
# delete items that are not needed for shallow JSON
# these are removed to match behavior of osxphotos < 0.59.0 (See #999, #1039)
for key in [
"adjustments",
"album_info",
"burst_album_info",
"burst_albums",
"burst_default_pick",
"burst_key",
"burst_photos",
"burst_selected",
"cloud_metadata",
"import_info",
"labels_normalized",
"path_derivatives",
"person_info",
"project_info",
"search_info_normalized",
"search_info",
]:
del dict_data[key]
for k, v in dict_data.items():
# sort lists such as keywords so JSON is consistent
# but do not sort certain items like location
@ -1903,7 +1935,7 @@ class PhotoInfo:
continue
if v and isinstance(v, (list, tuple)) and not isinstance(v[0], dict):
dict_data[k] = sorted(v, key=lambda v: v if v is not None else "")
return json.dumps(dict_data, sort_keys=True, default=default)
return json.dumps(dict_data, sort_keys=True, default=default, indent=indent)
def _json_hexdigest(self):
"""JSON for use by hexdigest()"""

View File

@ -1,6 +1,7 @@
""" Basic tests for Photos 5 on MacOS 10.15.7 """
import datetime
import json
import os
import os.path
import pathlib
@ -341,19 +342,16 @@ def test_init5(mocker):
def test_db_len(photosdb):
# assert photosdb.db_version in osxphotos._TESTED_DB_VERSIONS
assert len(photosdb) == PHOTOS_DB_LEN
def test_db_version(photosdb):
# assert photosdb.db_version in osxphotos._TESTED_DB_VERSIONS
assert photosdb.db_version == "6000"
def test_persons(photosdb):
assert "Katie" in photosdb.persons
assert Counter(PERSONS) == Counter(photosdb.persons)
@ -363,40 +361,34 @@ def test_photos_version(photosdb):
def test_keywords(photosdb):
assert "wedding" in photosdb.keywords
assert Counter(KEYWORDS) == Counter(photosdb.keywords)
def test_album_names(photosdb):
assert "Pumpkin Farm" in photosdb.albums
assert Counter(ALBUMS) == Counter(photosdb.albums)
def test_keywords_dict(photosdb):
keywords = photosdb.keywords_as_dict
assert keywords["wedding"] == 3
assert keywords == KEYWORDS_DICT
def test_persons_as_dict(photosdb):
persons = photosdb.persons_as_dict
assert persons["Maria"] == 2
assert persons == PERSONS_DICT
def test_albums_as_dict(photosdb):
albums = photosdb.albums_as_dict
assert albums["Pumpkin Farm"] == 3
assert albums == ALBUM_DICT
def test_album_sort_order(photosdb):
album = [a for a in photosdb.album_info if a.title == "Pumpkin Farm"][0]
photos = album.photos
@ -405,14 +397,12 @@ def test_album_sort_order(photosdb):
def test_album_empty_album(photosdb):
album = [a for a in photosdb.album_info if a.title == "EmptyAlbum"][0]
photos = album.photos
assert photos == []
def test_attributes(photosdb):
photos = photosdb.photos(uuid=["D79B8D77-BFFC-460B-9312-034F2877D35B"])
assert len(photos) == 1
p = photos[0]
@ -484,7 +474,6 @@ def test_attributes_2(photosdb):
def test_missing(photosdb):
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
assert len(photos) == 1
p = photos[0]
@ -493,7 +482,6 @@ def test_missing(photosdb):
def test_favorite(photosdb):
photos = photosdb.photos(uuid=[UUID_DICT["favorite"]])
assert len(photos) == 1
p = photos[0]
@ -501,7 +489,6 @@ def test_favorite(photosdb):
def test_not_favorite(photosdb):
photos = photosdb.photos(uuid=[UUID_DICT["not_favorite"]])
assert len(photos) == 1
p = photos[0]
@ -509,7 +496,6 @@ def test_not_favorite(photosdb):
def test_hidden(photosdb):
photos = photosdb.photos(uuid=[UUID_DICT["hidden"]])
assert len(photos) == 1
p = photos[0]
@ -517,7 +503,6 @@ def test_hidden(photosdb):
def test_not_hidden(photosdb):
photos = photosdb.photos(uuid=[UUID_DICT["not_hidden"]])
assert len(photos) == 1
p = photos[0]
@ -656,7 +641,6 @@ def test_not_ismovie(photosdb):
def test_count(photosdb):
photos = photosdb.photos()
assert len(photos) == PHOTOS_NOT_IN_TRASH_LEN
@ -735,13 +719,11 @@ def test_photoinfo_not_intrash(photosdb):
def test_keyword_2(photosdb):
photos = photosdb.photos(keywords=["wedding"])
assert len(photos) == 2 # won't show the one in the trash
def test_keyword_not_in_album(photosdb):
# find all photos with keyword "Kids" not in the album "Pumpkin Farm"
photos1 = photosdb.photos(albums=["Pumpkin Farm"])
photos2 = photosdb.photos(keywords=["Kids"])
@ -758,20 +740,17 @@ def test_album_folder_name(photosdb):
def test_multi_person(photosdb):
photos = photosdb.photos(persons=["Katie", "Suzy"])
assert len(photos) == 3
def test_get_db_path(photosdb):
db_path = photosdb.db_path
assert db_path.endswith(PHOTOS_DB_PATH)
def test_get_library_path(photosdb):
lib_path = photosdb.library_path
assert lib_path.endswith(PHOTOS_LIBRARY_PATH)
@ -1080,14 +1059,12 @@ def test_eq_2():
def test_not_eq(photosdb):
photos1 = photosdb.photos(uuid=[UUID_DICT["export"]])
photos2 = photosdb.photos(uuid=[UUID_DICT["missing"]])
assert photos1[0] != photos2[0]
def test_photosdb_repr():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photosdb2 = eval(repr(photosdb))
@ -1098,7 +1075,6 @@ def test_photosdb_repr():
def test_photosinfo_repr(photosdb):
photos = photosdb.photos(uuid=[UUID_DICT["favorite"]])
photo = photos[0]
photo2 = eval(repr(photo))
@ -1502,3 +1478,33 @@ def test_fingerprint(photosdb):
for uuid, fingerprint in UUID_FINGERPRINT.items():
photo = photosdb.get_photo(uuid)
assert photo.fingerprint == fingerprint
def test_asdict(photosdb: osxphotos.PhotosDB):
"""Test PhotoInfo.asdict()"""
photo = photosdb.get_photo(UUID_DICT["favorite"])
photo_dict = photo.asdict()
assert photo_dict["favorite"]
def test_json(photosdb: osxphotos.PhotosDB):
"""Test PhotoInfo.json()"""
photo = photosdb.get_photo(UUID_DICT["favorite"])
photo_dict = json.loads(photo.json())
assert photo_dict["favorite"]
def test_json_indent(photosdb: osxphotos.PhotosDB):
"""Test PhotoInfo.json() with indent"""
photo = photosdb.get_photo(UUID_DICT["favorite"])
photo_dict = json.loads(photo.json(indent=4))
assert photo_dict["favorite"]
assert "album_info" in photo_dict
def test_json_shallow(photosdb: osxphotos.PhotosDB):
"""Test PhotoInfo.json() with shallow=True"""
photo = photosdb.get_photo(UUID_DICT["favorite"])
photo_dict = json.loads(photo.json(shallow=True))
assert photo_dict["favorite"]
assert "album_info" not in photo_dict

View File

@ -1,5 +1,6 @@
"""Test macOS 13.0 Photos library"""
import json
from collections import namedtuple
import pytest
@ -660,7 +661,6 @@ def test_keyword_2(photosdb):
def test_keyword_not_in_album(photosdb):
# find all photos with keyword "Kids" not in the album "Pumpkin Farm"
photos1 = photosdb.photos(albums=["Pumpkin Farm"])
photos2 = photosdb.photos(keywords=["Kids"])
@ -1273,3 +1273,26 @@ def test_person_feature_less(photosdb):
photo = photosdb.get_photo(UUID_PERSON_NOT_FEATURE_LESS)
assert not photo.person_info[0].feature_less
def test_json(photosdb: osxphotos.PhotosDB):
"""Test PhotoInfo.json()"""
photo = photosdb.get_photo(UUID_DICT["favorite"])
photo_dict = json.loads(photo.json())
assert photo_dict["favorite"]
def test_json_indent(photosdb: osxphotos.PhotosDB):
"""Test PhotoInfo.json() with indent"""
photo = photosdb.get_photo(UUID_DICT["favorite"])
photo_dict = json.loads(photo.json(indent=4))
assert photo_dict["favorite"]
assert "album_info" in photo_dict
def test_json_shallow(photosdb: osxphotos.PhotosDB):
"""Test PhotoInfo.json() with shallow=True"""
photo = photosdb.get_photo(UUID_DICT["favorite"])
photo_dict = json.loads(photo.json(shallow=True))
assert photo_dict["favorite"]
assert "album_info" not in photo_dict