basic Photos 5 info now being read
This commit is contained in:
@@ -21,6 +21,7 @@ from . import _applescript
|
|||||||
# from loguru import logger
|
# from loguru import logger
|
||||||
|
|
||||||
# TODO: Add favorites, hidden
|
# TODO: Add favorites, hidden
|
||||||
|
# TODO: Add location
|
||||||
# TODO: Does not work with Photos 5.0 / Mac OS 10.15 Catalina
|
# TODO: Does not work with Photos 5.0 / Mac OS 10.15 Catalina
|
||||||
# TODO: standardize _ and __ as leading char for private variables
|
# TODO: standardize _ and __ as leading char for private variables
|
||||||
# TODO: fix docstrings
|
# TODO: fix docstrings
|
||||||
@@ -40,7 +41,7 @@ _PHOTOS_5_VERSION = "6000"
|
|||||||
# which major version operating systems have been tested
|
# which major version operating systems have been tested
|
||||||
_TESTED_OS_VERSIONS = ["12", "13", "14"]
|
_TESTED_OS_VERSIONS = ["12", "13", "14"]
|
||||||
|
|
||||||
_debug = False
|
_debug = True
|
||||||
|
|
||||||
|
|
||||||
def _get_os_version():
|
def _get_os_version():
|
||||||
@@ -626,10 +627,11 @@ class PhotosDB:
|
|||||||
""" process the Photos database to extract info """
|
""" process the Photos database to extract info """
|
||||||
""" works on Photos version >= 5.0 """
|
""" works on Photos version >= 5.0 """
|
||||||
|
|
||||||
print(f"DEBUG: _process_database5")
|
|
||||||
|
|
||||||
global _debug
|
global _debug
|
||||||
|
|
||||||
|
if _debug:
|
||||||
|
print(f"DEBUG: _process_database5")
|
||||||
|
|
||||||
# Epoch is Jan 1, 2001
|
# Epoch is Jan 1, 2001
|
||||||
td = (datetime(2001, 1, 1, 0, 0) - datetime(1970, 1, 1, 0, 0)).total_seconds()
|
td = (datetime(2001, 1, 1, 0, 0) - datetime(1970, 1, 1, 0, 0)).total_seconds()
|
||||||
|
|
||||||
@@ -772,35 +774,68 @@ class PhotosDB:
|
|||||||
pp.pprint(self._dbvolumes)
|
pp.pprint(self._dbvolumes)
|
||||||
# close_pbar_status()
|
# close_pbar_status()
|
||||||
|
|
||||||
#ZZZ
|
print(f"DEBUG: Getting information about photos")
|
||||||
sys.exit()
|
# TODO: Since I don't use progress bars now, can probably remove the count
|
||||||
# logger.debug("Getting information about photos")
|
|
||||||
c.execute(
|
c.execute(
|
||||||
"select count(*) from RKVersion, RKMaster where RKVersion.isInTrash = 0 and "
|
"SELECT COUNT(*) "
|
||||||
+ "RKVersion.type = 2 and RKVersion.masterUuid = RKMaster.uuid and "
|
"FROM ZGENERICASSET "
|
||||||
+ "RKVersion.filename not like '%.pdf'"
|
"JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = ZGENERICASSET.Z_PK "
|
||||||
|
"WHERE ZGENERICASSET.ZTRASHEDSTATE = 0 AND ZGENERICASSET.ZKIND = 0 "
|
||||||
)
|
)
|
||||||
# init_pbar_status("Photos", c.fetchone()[0])
|
# init_pbar_status("Photos", c.fetchone()[0])
|
||||||
c.execute(
|
c.execute(
|
||||||
"select RKVersion.uuid, RKVersion.modelId, RKVersion.masterUuid, RKVersion.filename, "
|
"SELECT ZGENERICASSET.ZUUID, "
|
||||||
+ "RKVersion.lastmodifieddate, RKVersion.imageDate, RKVersion.mainRating, "
|
"ZADDITIONALASSETATTRIBUTES.ZMASTERFINGERPRINT, "
|
||||||
+ "RKVersion.hasAdjustments, RKVersion.hasKeywords, RKVersion.imageTimeZoneOffsetSeconds, "
|
"ZADDITIONALASSETATTRIBUTES.ZTITLE, "
|
||||||
+ "RKMaster.volumeId, RKMaster.imagePath, RKVersion.extendedDescription, RKVersion.name, "
|
"ZADDITIONALASSETATTRIBUTES.ZORIGINALFILENAME, "
|
||||||
+ "RKMaster.isMissing "
|
"ZGENERICASSET.ZMODIFICATIONDATE, "
|
||||||
+ "from RKVersion, RKMaster where RKVersion.isInTrash = 0 and RKVersion.type = 2 and "
|
"ZGENERICASSET.ZDATECREATED, "
|
||||||
+ "RKVersion.masterUuid = RKMaster.uuid and RKVersion.filename not like '%.pdf'"
|
"ZADDITIONALASSETATTRIBUTES.ZTIMEZONEOFFSET, "
|
||||||
|
"ZADDITIONALASSETATTRIBUTES.ZINFERREDTIMEZONEOFFSET, "
|
||||||
|
"ZADDITIONALASSETATTRIBUTES.ZTIMEZONENAME, "
|
||||||
|
"ZGENERICASSET.ZHIDDEN, "
|
||||||
|
"ZGENERICASSET.ZFAVORITE, "
|
||||||
|
"ZGENERICASSET.ZDIRECTORY, "
|
||||||
|
"ZGENERICASSET.ZFILENAME "
|
||||||
|
"FROM ZGENERICASSET "
|
||||||
|
"JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = ZGENERICASSET.Z_PK "
|
||||||
|
"WHERE ZGENERICASSET.ZTRASHEDSTATE = 0 AND ZGENERICASSET.ZKIND = 0 "
|
||||||
|
"ORDER BY ZGENERICASSET.ZUUID "
|
||||||
|
# "select RKVersion.uuid, RKVersion.modelId, RKVersion.masterUuid, RKVersion.filename, "
|
||||||
|
# + "RKVersion.lastmodifieddate, RKVersion.imageDate, RKVersion.mainRating, "
|
||||||
|
# + "RKVersion.hasAdjustments, RKVersion.hasKeywords, RKVersion.imageTimeZoneOffsetSeconds, "
|
||||||
|
# + "RKMaster.volumeId, RKMaster.imagePath, RKVersion.extendedDescription, RKVersion.name, "
|
||||||
|
# + "RKMaster.isMissing "
|
||||||
|
# + "from RKVersion, RKMaster where RKVersion.isInTrash = 0 and RKVersion.type = 2 and "
|
||||||
|
# + "RKVersion.masterUuid = RKMaster.uuid and RKVersion.filename not like '%.pdf'"
|
||||||
)
|
)
|
||||||
|
# Order of results
|
||||||
|
# 0 "SELECT ZGENERICASSET.ZUUID, "
|
||||||
|
# 1 "ZADDITIONALASSETATTRIBUTES.ZMASTERFINGERPRINT, "
|
||||||
|
# 2 "ZADDITIONALASSETATTRIBUTES.ZTITLE, "
|
||||||
|
# 3 "ZADDITIONALASSETATTRIBUTES.ZORIGINALFILENAME, "
|
||||||
|
# 4 "ZGENERICASSET.ZMODIFICATIONDATE, "
|
||||||
|
# 5 "ZGENERICASSET.ZDATECREATED, "
|
||||||
|
# 6 "ZADDITIONALASSETATTRIBUTES.ZTIMEZONEOFFSET, "
|
||||||
|
# 7 "ZADDITIONALASSETATTRIBUTES.ZINFERREDTIMEZONEOFFSET, "
|
||||||
|
# 8 "ZADDITIONALASSETATTRIBUTES.ZTIMEZONENAME, "
|
||||||
|
# 9 "ZGENERICASSET.ZHIDDEN, "
|
||||||
|
# 10 "ZGENERICASSET.ZFAVORITE, "
|
||||||
|
# 11 "ZGENERICASSET.ZDIRECTORY, "
|
||||||
|
# 12 "ZGENERICASSET.ZFILENAME "
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
for row in c:
|
for row in c:
|
||||||
# set_pbar_status(i)
|
# set_pbar_status(i)
|
||||||
i = i + 1
|
i = i + 1
|
||||||
uuid = row[0]
|
uuid = row[0]
|
||||||
if _debug:
|
if _debug:
|
||||||
print(f"i = {i:d}, uuid = '{uuid}, master = '{row[2]}")
|
print(f"i = {i:d}, uuid = '{uuid}")
|
||||||
self._dbphotos[uuid] = {}
|
self._dbphotos[uuid] = {}
|
||||||
self._dbphotos[uuid]["modelID"] = row[1]
|
self._dbphotos[uuid]["modelID"] = None
|
||||||
self._dbphotos[uuid]["masterUuid"] = row[2]
|
self._dbphotos[uuid]["masterUuid"] = None
|
||||||
self._dbphotos[uuid]["filename"] = row[3]
|
self._dbphotos[uuid]["masterFingerprint"] = row[1]
|
||||||
|
self._dbphotos[uuid]["name"] = row[2]
|
||||||
try:
|
try:
|
||||||
self._dbphotos[uuid]["lastmodifieddate"] = datetime.fromtimestamp(
|
self._dbphotos[uuid]["lastmodifieddate"] = datetime.fromtimestamp(
|
||||||
row[4] + td
|
row[4] + td
|
||||||
@@ -813,15 +848,19 @@ class PhotosDB:
|
|||||||
self._dbphotos[uuid]["imageDate"] = datetime.fromtimestamp(
|
self._dbphotos[uuid]["imageDate"] = datetime.fromtimestamp(
|
||||||
row[5] + td
|
row[5] + td
|
||||||
) # - row[9], timezone.utc)
|
) # - row[9], timezone.utc)
|
||||||
self._dbphotos[uuid]["mainRating"] = row[6]
|
# self._dbphotos[uuid]["mainRating"] = row[6]
|
||||||
self._dbphotos[uuid]["hasAdjustments"] = row[7]
|
# self._dbphotos[uuid]["hasAdjustments"] = row[7]
|
||||||
self._dbphotos[uuid]["hasKeywords"] = row[8]
|
# self._dbphotos[uuid]["hasKeywords"] = row[8]
|
||||||
self._dbphotos[uuid]["imageTimeZoneOffsetSeconds"] = row[9]
|
self._dbphotos[uuid]["imageTimeZoneOffsetSeconds"] = row[6]
|
||||||
self._dbphotos[uuid]["volumeId"] = row[10]
|
# self._dbphotos[uuid]["volumeId"] = row[10]
|
||||||
self._dbphotos[uuid]["imagePath"] = row[11]
|
# self._dbphotos[uuid]["imagePath"] = row[11]
|
||||||
self._dbphotos[uuid]["extendedDescription"] = row[12]
|
# self._dbphotos[uuid]["extendedDescription"] = row[12]
|
||||||
self._dbphotos[uuid]["name"] = row[13]
|
self._dbphotos[uuid]["hidden"] = row[9]
|
||||||
self._dbphotos[uuid]["isMissing"] = row[14]
|
self._dbphotos[uuid]["favorite"] = row[10]
|
||||||
|
self._dbphotos[uuid]["originalFilename"] = row[3]
|
||||||
|
self._dbphotos[uuid]["filename"] = row[12]
|
||||||
|
self._dbphotos[uuid]["directory"] = row[11]
|
||||||
|
# self._dbphotos[uuid]["isMissing"] = row[14]
|
||||||
# logger.debug(
|
# logger.debug(
|
||||||
# "Fetching data for photo %d %s %s %s %s %s: %s"
|
# "Fetching data for photo %d %s %s %s %s %s: %s"
|
||||||
# % (
|
# % (
|
||||||
@@ -836,14 +875,60 @@ class PhotosDB:
|
|||||||
# )
|
# )
|
||||||
|
|
||||||
# close_pbar_status()
|
# close_pbar_status()
|
||||||
conn.close()
|
|
||||||
|
# Get extended description
|
||||||
|
c.execute(
|
||||||
|
"SELECT ZGENERICASSET.ZUUID, "
|
||||||
|
"ZASSETDESCRIPTION.ZLONGDESCRIPTION "
|
||||||
|
"FROM ZGENERICASSET "
|
||||||
|
"JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = ZGENERICASSET.Z_PK "
|
||||||
|
"JOIN ZASSETDESCRIPTION ON ZASSETDESCRIPTION.Z_PK = ZADDITIONALASSETATTRIBUTES.ZASSETDESCRIPTION "
|
||||||
|
"ORDER BY ZGENERICASSET.ZUUID "
|
||||||
|
)
|
||||||
|
i = 0
|
||||||
|
for row in c:
|
||||||
|
i = i + 1
|
||||||
|
uuid = row[0]
|
||||||
|
if uuid in self._dbphotos:
|
||||||
|
self._dbphotos[uuid]["extendedDescription"] = row[1]
|
||||||
|
else:
|
||||||
|
print(
|
||||||
|
f"DEBUG WARNING: found description {row[1]} but no photo for {uuid}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# get information on local/remote availability
|
||||||
|
c.execute(
|
||||||
|
"SELECT ZGENERICASSET.ZUUID, "
|
||||||
|
"ZINTERNALRESOURCE.ZLOCALAVAILABILITY, "
|
||||||
|
"ZINTERNALRESOURCE.ZREMOTEAVAILABILITY "
|
||||||
|
"FROM ZGENERICASSET "
|
||||||
|
"JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = ZGENERICASSET.Z_PK "
|
||||||
|
"JOIN ZINTERNALRESOURCE ON ZINTERNALRESOURCE.ZFINGERPRINT = ZADDITIONALASSETATTRIBUTES.ZMASTERFINGERPRINT "
|
||||||
|
)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for row in c:
|
||||||
|
i = i+1
|
||||||
|
uuid = row[0]
|
||||||
|
if uuid in self._dbphotos:
|
||||||
|
self._dbphotos[uuid]["localAvailability"] = row[1]
|
||||||
|
self._dbphotos[uuid]["remoteAvailability"] = row[2]
|
||||||
|
if row[1] != 1:
|
||||||
|
self._dbphotos[uuid]["isMissing"] = 1
|
||||||
|
else:
|
||||||
|
self._dbphotos[uuid]["isMissing"] = 0
|
||||||
|
|
||||||
|
if _debug:
|
||||||
|
pp.pprint(self._dbphotos)
|
||||||
|
|
||||||
# add faces and keywords to photo data
|
# add faces and keywords to photo data
|
||||||
for uuid in self._dbphotos:
|
for uuid in self._dbphotos:
|
||||||
# keywords
|
# keywords
|
||||||
if self._dbphotos[uuid]["hasKeywords"] == 1:
|
if uuid in self._dbkeywords_uuid:
|
||||||
|
self._dbphotos[uuid]["hasKeywords"] = 1
|
||||||
self._dbphotos[uuid]["keywords"] = self._dbkeywords_uuid[uuid]
|
self._dbphotos[uuid]["keywords"] = self._dbkeywords_uuid[uuid]
|
||||||
else:
|
else:
|
||||||
|
self._dbphotos[uuid]["hasKeywords"] = 0
|
||||||
self._dbphotos[uuid]["keywords"] = []
|
self._dbphotos[uuid]["keywords"] = []
|
||||||
|
|
||||||
if uuid in self._dbfaces_uuid:
|
if uuid in self._dbfaces_uuid:
|
||||||
@@ -860,14 +945,15 @@ class PhotosDB:
|
|||||||
self._dbphotos[uuid]["albums"] = []
|
self._dbphotos[uuid]["albums"] = []
|
||||||
self._dbphotos[uuid]["hasAlbums"] = 0
|
self._dbphotos[uuid]["hasAlbums"] = 0
|
||||||
|
|
||||||
if self._dbphotos[uuid]["volumeId"] is not None:
|
# if self._dbphotos[uuid]["volumeId"] is not None:
|
||||||
self._dbphotos[uuid]["volume"] = self._dbvolumes[
|
# self._dbphotos[uuid]["volume"] = self._dbvolumes[
|
||||||
self._dbphotos[uuid]["volumeId"]
|
# self._dbphotos[uuid]["volumeId"]
|
||||||
]
|
# ]
|
||||||
else:
|
# else:
|
||||||
self._dbphotos[uuid]["volume"] = None
|
# self._dbphotos[uuid]["volume"] = None
|
||||||
|
|
||||||
# remove temporary files
|
# close connection and remove temporary files
|
||||||
|
conn.close()
|
||||||
self._cleanup_tmp_files()
|
self._cleanup_tmp_files()
|
||||||
|
|
||||||
if _debug:
|
if _debug:
|
||||||
|
|||||||
Reference in New Issue
Block a user