Fix for path_raw when file is reference, #480

This commit is contained in:
Rhet Turnbull
2021-07-02 12:39:41 -07:00
parent f32c4f4acd
commit 4cc3220287
3 changed files with 108 additions and 63 deletions

View File

@@ -1,3 +1,3 @@
""" version info """ """ version info """
__version__ = "0.42.51" __version__ = "0.42.52"

View File

@@ -149,41 +149,11 @@ class PhotoInfo:
except AttributeError: except AttributeError:
self._path = None self._path = None
photopath = None photopath = None
# TODO: should path try to return path even if ismissing?
if self._info["isMissing"] == 1: if self._info["isMissing"] == 1:
return photopath # path would be meaningless until downloaded return photopath # path would be meaningless until downloaded
if self._db._db_version <= _PHOTOS_4_VERSION: if self._db._db_version <= _PHOTOS_4_VERSION:
if self._info["has_raw"]: return self._path_4()
# return the path to JPEG even if RAW is original
vol = (
self._db._dbvolumes[self._info["raw_pair_info"]["volumeId"]]
if self._info["raw_pair_info"]["volumeId"] is not None
else None
)
if vol is not None:
photopath = os.path.join(
"/Volumes", vol, self._info["raw_pair_info"]["imagePath"]
)
else:
photopath = os.path.join(
self._db._masters_path,
self._info["raw_pair_info"]["imagePath"],
)
else:
vol = self._info["volume"]
if vol is not None:
photopath = os.path.join(
"/Volumes", vol, self._info["imagePath"]
)
else:
photopath = os.path.join(
self._db._masters_path, self._info["imagePath"]
)
if not os.path.isfile(photopath):
photopath = None
self._path = photopath
return photopath
if self._info["shared"]: if self._info["shared"]:
# shared photo # shared photo
@@ -213,6 +183,37 @@ class PhotoInfo:
self._path = photopath self._path = photopath
return photopath return photopath
def _path_4(self):
"""return path for photo on Photos <= version 4"""
if self._info["has_raw"]:
# return the path to JPEG even if RAW is original
vol = (
self._db._dbvolumes[self._info["raw_pair_info"]["volumeId"]]
if self._info["raw_pair_info"]["volumeId"] is not None
else None
)
if vol is not None:
photopath = os.path.join(
"/Volumes", vol, self._info["raw_pair_info"]["imagePath"]
)
else:
photopath = os.path.join(
self._db._masters_path,
self._info["raw_pair_info"]["imagePath"],
)
else:
vol = self._info["volume"]
if vol is not None:
photopath = os.path.join("/Volumes", vol, self._info["imagePath"])
else:
photopath = os.path.join(
self._db._masters_path, self._info["imagePath"]
)
if not os.path.isfile(photopath):
photopath = None
self._path = photopath
return photopath
@property @property
def path_edited(self): def path_edited(self):
"""absolute path on disk of the edited picture""" """absolute path on disk of the edited picture"""
@@ -252,14 +253,10 @@ class PhotoInfo:
filename = None filename = None
if self._info["type"] == _PHOTO_TYPE: if self._info["type"] == _PHOTO_TYPE:
# it's a photo # it's a photo
if self._db._photos_ver == 5: if self._db._photos_ver != 5 and self.uti == "public.heic":
filename = f"{self._uuid}_1_201_a.jpeg" filename = f"{self._uuid}_1_201_a.heic"
else: else:
# could be a heic or a jpeg filename = f"{self._uuid}_1_201_a.jpeg"
if self.uti == "public.heic":
filename = f"{self._uuid}_1_201_a.heic"
else:
filename = f"{self._uuid}_1_201_a.jpeg"
elif self._info["type"] == _MOVIE_TYPE: elif self._info["type"] == _MOVIE_TYPE:
# it's a movie # it's a movie
filename = f"{self._uuid}_2_0_a.mov" filename = f"{self._uuid}_2_0_a.mov"
@@ -374,21 +371,9 @@ class PhotoInfo:
# return photopath # return photopath
if self._db._db_version <= _PHOTOS_4_VERSION: if self._db._db_version <= _PHOTOS_4_VERSION:
vol = self._info["raw_info"]["volume"] return self._path_raw_4()
if vol is not None:
photopath = os.path.join( if not self.isreference:
"/Volumes", vol, self._info["raw_info"]["imagePath"]
)
else:
photopath = os.path.join(
self._db._masters_path, self._info["raw_info"]["imagePath"]
)
if not os.path.isfile(photopath):
logging.debug(
f"MISSING PATH: RAW photo for UUID {self._uuid} should be at {photopath} but does not appear to exist"
)
photopath = None
else:
filestem = pathlib.Path(self._info["filename"]).stem filestem = pathlib.Path(self._info["filename"]).stem
# raw_ext = get_preferred_uti_extension(self._info["UTI_raw"]) # raw_ext = get_preferred_uti_extension(self._info["UTI_raw"])
@@ -405,12 +390,40 @@ class PhotoInfo:
if not raw_file: if not raw_file:
photopath = None photopath = None
else: else:
photopath = os.path.join(filepath, raw_file[0]) photopath = pathlib.Path(filepath) / raw_file[0]
if not os.path.isfile(photopath): photopath = str(photopath) if photopath.is_file() else None
photopath = None else:
# is a reference
try:
photopath = (
pathlib.Path("/Volumes")
/ self._info["raw_volume"]
/ self._info["raw_relative_path"]
)
photopath = str(photopath) if photopath.is_file() else None
except KeyError:
# don't have the path details
photopath = None
return photopath return photopath
def _path_raw_4(self):
"""Return path_raw for Photos <= version 4"""
vol = self._info["raw_info"]["volume"]
if vol is not None:
photopath = os.path.join(
"/Volumes", vol, self._info["raw_info"]["imagePath"]
)
else:
photopath = os.path.join(
self._db._masters_path, self._info["raw_info"]["imagePath"]
)
if not os.path.isfile(photopath):
logging.debug(
f"MISSING PATH: RAW photo for UUID {self._uuid} should be at {photopath} but does not appear to exist"
)
photopath = None
@property @property
def description(self): def description(self):
"""long / extended description of picture""" """long / extended description of picture"""

View File

@@ -246,6 +246,9 @@ class PhotosDB:
# key is tuple of (original_filesize, date) and value is list of uuids that match that signature # key is tuple of (original_filesize, date) and value is list of uuids that match that signature
self._db_signatures = {} self._db_signatures = {}
# Dict to hold information on volume names (Photos 5+)
self._db_filesystem_volumes = {}
if _debug(): if _debug():
logging.debug(f"dbfile = {dbfile}") logging.debug(f"dbfile = {dbfile}")
@@ -599,9 +602,9 @@ class PhotosDB:
verbose = self._verbose verbose = self._verbose
verbose("Processing database.") verbose("Processing database.")
verbose(f"Database version: {self._db_version}.") verbose(f"Database version: {self._db_version}.")
self._photos_ver = 4 # only used in Photos 5+ self._photos_ver = 4 # only used in Photos 5+
(conn, c) = _open_sql_file(self._tmp_db) (conn, c) = _open_sql_file(self._tmp_db)
# get info to associate persons with photos # get info to associate persons with photos
@@ -2348,7 +2351,8 @@ class PhotosDB:
ZINTERNALRESOURCE.ZDATALENGTH, ZINTERNALRESOURCE.ZDATALENGTH,
null, null,
ZINTERNALRESOURCE.ZDATASTORESUBTYPE, ZINTERNALRESOURCE.ZDATASTORESUBTYPE,
ZINTERNALRESOURCE.ZRESOURCETYPE ZINTERNALRESOURCE.ZRESOURCETYPE,
ZINTERNALRESOURCE.ZFILESYSTEMBOOKMARK
FROM {asset_table} FROM {asset_table}
JOIN ZINTERNALRESOURCE ON ZINTERNALRESOURCE.ZASSET = ZADDITIONALASSETATTRIBUTES.ZASSET JOIN ZINTERNALRESOURCE ON ZINTERNALRESOURCE.ZASSET = ZADDITIONALASSETATTRIBUTES.ZASSET
JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = {asset_table}.Z_PK JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = {asset_table}.Z_PK
@@ -2360,14 +2364,15 @@ class PhotosDB:
ZINTERNALRESOURCE.ZDATALENGTH, ZINTERNALRESOURCE.ZDATALENGTH,
ZUNIFORMTYPEIDENTIFIER.ZIDENTIFIER, ZUNIFORMTYPEIDENTIFIER.ZIDENTIFIER,
ZINTERNALRESOURCE.ZDATASTORESUBTYPE, ZINTERNALRESOURCE.ZDATASTORESUBTYPE,
ZINTERNALRESOURCE.ZRESOURCETYPE ZINTERNALRESOURCE.ZRESOURCETYPE,
ZINTERNALRESOURCE.ZFILESYSTEMBOOKMARK
FROM {asset_table} FROM {asset_table}
JOIN ZINTERNALRESOURCE ON ZINTERNALRESOURCE.ZASSET = ZADDITIONALASSETATTRIBUTES.ZASSET JOIN ZINTERNALRESOURCE ON ZINTERNALRESOURCE.ZASSET = ZADDITIONALASSETATTRIBUTES.ZASSET
JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = {asset_table}.Z_PK JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = {asset_table}.Z_PK
JOIN ZUNIFORMTYPEIDENTIFIER ON ZUNIFORMTYPEIDENTIFIER.Z_PK = ZINTERNALRESOURCE.ZUNIFORMTYPEIDENTIFIER JOIN ZUNIFORMTYPEIDENTIFIER ON ZUNIFORMTYPEIDENTIFIER.Z_PK = ZINTERNALRESOURCE.ZUNIFORMTYPEIDENTIFIER
WHERE ZINTERNALRESOURCE.ZDATASTORESUBTYPE = 17 WHERE ZINTERNALRESOURCE.ZDATASTORESUBTYPE = 17
""" """
c.execute(sql_raw) c.execute(sql_raw)
for row in c: for row in c:
@@ -2378,6 +2383,33 @@ class PhotosDB:
self._dbphotos[uuid]["UTI_raw"] = row[2] self._dbphotos[uuid]["UTI_raw"] = row[2]
self._dbphotos[uuid]["datastore_subtype"] = row[3] self._dbphotos[uuid]["datastore_subtype"] = row[3]
self._dbphotos[uuid]["resource_type"] = row[4] self._dbphotos[uuid]["resource_type"] = row[4]
self._dbphotos[uuid]["raw_bookmark"] = row[5]
# get paths for the relative imports for RAW+JPEG images
c.execute(
f""" SELECT
{asset_table}.ZUUID,
ZFILESYSTEMVOLUME.ZNAME,
ZFILESYSTEMBOOKMARK.ZPATHRELATIVETOVOLUME
FROM {asset_table}
JOIN ZINTERNALRESOURCE ON ZINTERNALRESOURCE.ZASSET = ZADDITIONALASSETATTRIBUTES.ZASSET
JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = {asset_table}.Z_PK
JOIN ZFILESYSTEMBOOKMARK ON ZFILESYSTEMBOOKMARK.ZRESOURCE = ZINTERNALRESOURCE.Z_PK
JOIN ZFILESYSTEMVOLUME ON ZFILESYSTEMVOLUME.Z_PK = ZINTERNALRESOURCE.ZFILESYSTEMVOLUME
WHERE ZINTERNALRESOURCE.ZDATASTORESUBTYPE = 17
"""
)
# path to the raw image will be /Volumes/ZFILESYSTEMVOLUME.ZNAME/ZFILESYSTEMBOOKMARK.ZPATHRELATIVETOVOLUME
# 0: {asset_table}.ZUUID, -- UUID
# 1: ZFILESYSTEMVOLUME.ZNAME, -- name of the volume
# 2: ZFILESYSTEMBOOKMARK.ZPATHRELATIVETOVOLUME -- path to the raw image
for row in c:
uuid = row[0]
if uuid in self._dbphotos:
self._dbphotos[uuid]["raw_volume"] = row[1]
self._dbphotos[uuid]["raw_relative_path"] = row[2]
# add faces and keywords to photo data # add faces and keywords to photo data
for uuid in self._dbphotos: for uuid in self._dbphotos: