Lots of work on export code

This commit is contained in:
Rhet Turnbull
2020-03-15 10:08:56 -07:00
parent c11afbaa6e
commit 0940f039d3
11 changed files with 370 additions and 238 deletions

View File

@@ -725,6 +725,7 @@ Export photo from the Photos library to another destination on disk.
- use_photos_export: boolean; (default=False), if True will attempt to export photo via applescript interaction with Photos; useful for forcing download of missing photos. This only works if the Photos library being used is the default library (last opened by Photos) as applescript will directly interact with whichever library Photos is currently using. - use_photos_export: boolean; (default=False), if True will attempt to export photo via applescript interaction with Photos; useful for forcing download of missing photos. This only works if the Photos library being used is the default library (last opened by Photos) as applescript will directly interact with whichever library Photos is currently using.
- timeout: (int, default=120) timeout in seconds used with use_photos_export - timeout: (int, default=120) timeout in seconds used with use_photos_export
- exiftool: (boolean, default = False) if True, will use [exiftool](https://exiftool.org/) to write metadata directly to the exported photo; exiftool must be installed and in the system path - exiftool: (boolean, default = False) if True, will use [exiftool](https://exiftool.org/) to write metadata directly to the exported photo; exiftool must be installed and in the system path
Returns: list of paths to exported files. More than one file could be exported, for example if live_photo=True, both the original imaage and the associated .mov file will be exported
The json sidecar file can be used by exiftool to apply the metadata from the json file to the image. For example: The json sidecar file can be used by exiftool to apply the metadata from the json file to the image. For example:
@@ -742,7 +743,6 @@ Then
If overwrite=False and increment=False, export will fail if destination file already exists If overwrite=False and increment=False, export will fail if destination file already exists
Returns the full path to the exported file
**Implementation Note**: Because the usual python file copy methods don't preserve all the metadata available on MacOS, export uses /usr/bin/ditto to do the copy for export. ditto preserves most metadata such as extended attributes, permissions, ACLs, etc. **Implementation Note**: Because the usual python file copy methods don't preserve all the metadata available on MacOS, export uses /usr/bin/ditto to do the copy for export. ditto preserves most metadata such as extended attributes, permissions, ACLs, etc.

View File

@@ -1344,7 +1344,7 @@ def export_photo(
overwrite=overwrite, overwrite=overwrite,
use_photos_export=use_photos_export, use_photos_export=use_photos_export,
exiftool=exiftool, exiftool=exiftool,
) )[0]
# if export-edited, also export the edited version # if export-edited, also export the edited version
# verify the photo has adjustments and valid path to avoid raising an exception # verify the photo has adjustments and valid path to avoid raising an exception

View File

@@ -1,3 +1,3 @@
""" version info """ """ version info """
__version__ = "0.22.21" __version__ = "0.22.23"

View File

@@ -505,7 +505,7 @@ class PhotoInfo:
): ):
""" export photo """ export photo
dest: must be valid destination path (or exception raised) dest: must be valid destination path (or exception raised)
filename: (optional): name of picture; if not provided, will use current filename filename: (optional): name of exported picture; if not provided, will use current filename
**NOTE**: if provided, user must ensure file extension (suffix) is correct. **NOTE**: if provided, user must ensure file extension (suffix) is correct.
For example, if photo is .CR2 file, edited image may be .jpeg. For example, if photo is .CR2 file, edited image may be .jpeg.
If you provide an extension different than what the actual file is, If you provide an extension different than what the actual file is,
@@ -525,12 +525,17 @@ class PhotoInfo:
use_photos_export: (boolean, default=False); if True will attempt to export photo via applescript interaction with Photos use_photos_export: (boolean, default=False); if True will attempt to export photo via applescript interaction with Photos
timeout: (int, default=120) timeout in seconds used with use_photos_export timeout: (int, default=120) timeout in seconds used with use_photos_export
exiftool: (boolean, default = False); if True, will use exiftool to write metadata to export file exiftool: (boolean, default = False); if True, will use exiftool to write metadata to export file
returns the full path to the exported file """ returns list of full paths to the exported files """
# list of all files exported during this call to export # list of all files exported during this call to export
exported_files = [] exported_files = []
logging.debug(f"dest ={dest}.filename={filename}") # check edited and raise exception trying to export edited version of
# photo that hasn't been edited
if edited and not self.hasadjustments:
raise ValueError(
"Photo does not have adjustments, cannot export edited version"
)
# check arguments and get destination path and filename (if provided) # check arguments and get destination path and filename (if provided)
if filename and len(filename) > 2: if filename and len(filename) > 2:
@@ -545,8 +550,8 @@ class PhotoInfo:
raise FileNotFoundError("Invalid path passed to export") raise FileNotFoundError("Invalid path passed to export")
if filename and len(filename) == 1: if filename and len(filename) == 1:
# if filename passed, use it, but verify extension # if filename passed, use it
filename = filename[0] fname = filename[0]
else: else:
# no filename provided so use the default # no filename provided so use the default
# if edited file requested, use filename but add _edited # if edited file requested, use filename but add _edited
@@ -560,25 +565,26 @@ class PhotoInfo:
) )
edited_name = pathlib.Path(self.path_edited).name edited_name = pathlib.Path(self.path_edited).name
edited_suffix = pathlib.Path(edited_name).suffix edited_suffix = pathlib.Path(edited_name).suffix
filename = ( fname = pathlib.Path(self.filename).stem + "_edited" + edited_suffix
pathlib.Path(self.filename).stem + "_edited" + edited_suffix
)
else: else:
filename = self.filename fname = self.filename
# check destination path # check destination path
dest = pathlib.Path(dest) dest = pathlib.Path(dest)
filename = pathlib.Path(filename) fname = pathlib.Path(fname)
logging.debug(f"dest ={dest}.filename={filename}") dest = dest / fname
dest = dest / filename
# check extension of destination # check extension of destination
if edited and self.path_edited is not None: if edited and self.path_edited is not None:
# use suffix from edited file
actual_suffix = pathlib.Path(self.path_edited).suffix actual_suffix = pathlib.Path(self.path_edited).suffix
elif edited: elif edited:
logging.warning("Invalid suffix check for missing edited file") # use .jpeg as that's probably correct
actual_suffix = "" # if edited and path_edited is None, will raise FileNotFoundError below
# unless use_photos_export is True
actual_suffix = ".jpeg"
else: else:
# use suffix from the non-edited file
actual_suffix = pathlib.Path(self.filename).suffix actual_suffix = pathlib.Path(self.filename).suffix
if dest.suffix != actual_suffix: if dest.suffix != actual_suffix:
@@ -613,16 +619,11 @@ class PhotoInfo:
# get path to source file and verify it's not None and is valid file # get path to source file and verify it's not None and is valid file
# TODO: how to handle ismissing or not hasadjustments and edited=True cases? # TODO: how to handle ismissing or not hasadjustments and edited=True cases?
if edited: if edited:
if not self.hasadjustments:
logging.warning(
"Attempting to export edited photo but hasadjustments=False"
)
if self.path_edited is not None: if self.path_edited is not None:
src = self.path_edited src = self.path_edited
else: else:
raise FileNotFoundError( raise FileNotFoundError(
f"edited=True but path_edited is none; hasadjustments: {self.hasadjustments}" f"Cannot export edited photo if path_edited is None"
) )
else: else:
if self.ismissing: if self.ismissing:
@@ -630,13 +631,10 @@ class PhotoInfo:
f"Attempting to export photo with ismissing=True: path = {self.path}" f"Attempting to export photo with ismissing=True: path = {self.path}"
) )
if self.path is None: if self.path is not None:
logging.warning(
f"Attempting to export photo but path is None: ismissing = {self.ismissing}"
)
raise FileNotFoundError("Cannot export photo if path is None")
else:
src = self.path src = self.path
else:
raise FileNotFoundError("Cannot export photo if path is None")
if not os.path.isfile(src): if not os.path.isfile(src):
raise FileNotFoundError(f"{src} does not appear to exist") raise FileNotFoundError(f"{src} does not appear to exist")
@@ -675,16 +673,18 @@ class PhotoInfo:
else: else:
# didn't get passed a filename, add _edited # didn't get passed a filename, add _edited
filestem = f"{dest.stem}_edited" filestem = f"{dest.stem}_edited"
exported = _export_photo_uuid_applescript( dest = dest.parent / f"{filestem}.jpeg"
self.uuid,
dest.parent, exported = _export_photo_uuid_applescript(
filestem=filestem, self.uuid,
original=False, dest.parent,
edited=True, filestem=filestem,
live_photo=live_photo, original=False,
timeout=timeout, edited=True,
burst=self.burst, live_photo=live_photo,
) timeout=timeout,
burst=self.burst,
)
else: else:
# export original version and not edited # export original version and not edited
filestem = dest.stem filestem = dest.stem
@@ -702,7 +702,9 @@ class PhotoInfo:
if exported is not None: if exported is not None:
exported_files.extend(exported) exported_files.extend(exported)
else: else:
logging.warning(f"Error exporting photo {self.uuid} to {dest}") logging.warning(
f"Error exporting photo {self.uuid} to {dest} with use_photos_export"
)
if sidecar_json: if sidecar_json:
logging.debug("writing exiftool_json_sidecar") logging.debug("writing exiftool_json_sidecar")
@@ -724,14 +726,12 @@ class PhotoInfo:
logging.warning(f"Error writing xmp sidecar to {sidecar_filename}") logging.warning(f"Error writing xmp sidecar to {sidecar_filename}")
raise e raise e
logging.debug(f"export exported_files: {exported_files}")
# if exiftool, write the metadata # if exiftool, write the metadata
if exiftool and exported_files: if exiftool and exported_files:
for exported_file in exported_files: for exported_file in exported_files:
self._write_exif_data(exported_file) self._write_exif_data(exported_file)
return str(dest) return exported_files
def _write_exif_data(self, filepath): def _write_exif_data(self, filepath):
""" write exif data to image file at filepath """ write exif data to image file at filepath
@@ -771,7 +771,6 @@ class PhotoInfo:
exif = {} exif = {}
exif["_CreatedBy"] = "osxphotos, https://github.com/RhetTbull/osxphotos" exif["_CreatedBy"] = "osxphotos, https://github.com/RhetTbull/osxphotos"
exif["File:FileName"] = self.filename
if self.description: if self.description:
exif["EXIF:ImageDescription"] = self.description exif["EXIF:ImageDescription"] = self.description

View File

@@ -255,7 +255,7 @@ def list_photo_libraries():
# On older MacOS versions, mdfind appears to ignore some libraries # On older MacOS versions, mdfind appears to ignore some libraries
# glob to find libraries in ~/Pictures then mdfind to find all the others # glob to find libraries in ~/Pictures then mdfind to find all the others
# TODO: make this more robust # TODO: make this more robust
lib_list = glob.glob(f"{str(Path.home())}/Pictures/*.photoslibrary") lib_list = glob.glob(f"{str(pathlib.Path.home())}/Pictures/*.photoslibrary")
# On older OS, may not get all libraries so make sure we get the last one # On older OS, may not get all libraries so make sure we get the last one
last_lib = get_last_library_path() last_lib = get_last_library_path()
@@ -327,7 +327,8 @@ def _export_photo_uuid_applescript(
If filestem.ext exists, it wil be overwritten If filestem.ext exists, it wil be overwritten
original: (boolean) if True, export original image; default = True original: (boolean) if True, export original image; default = True
edited: (boolean) if True, export edited photo; default = False edited: (boolean) if True, export edited photo; default = False
will produce an error if image does not have edits/adjustments If photo not edited and edited=True, will still export the original image
caller must verify image has been edited
*Note*: must be called with either edited or original but not both, *Note*: must be called with either edited or original but not both,
will raise error if called with both edited and original = True will raise error if called with both edited and original = True
live_photo: (boolean) if True, export associated .mov live photo; default = False live_photo: (boolean) if True, export associated .mov live photo; default = False
@@ -448,7 +449,7 @@ def _db_is_locked(dbname):
conn.close() conn.close()
logging.debug(f"{dbname} is not locked") logging.debug(f"{dbname} is not locked")
locked = False locked = False
except Exception as e: except:
logging.debug(f"{dbname} is locked") logging.debug(f"{dbname} is locked")
locked = True locked = True

View File

@@ -415,20 +415,18 @@ def test_export_1():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest) got_dest = photos[0].export(dest)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
assert os.path.isfile(got_dest) assert os.path.isfile(got_dest)
# remove the temporary file
os.remove(got_dest)
def test_export_2(): def test_export_2():
# test export with user provided filename # test export with user provided filename
@@ -439,21 +437,19 @@ def test_export_2():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
timestamp = time.time() timestamp = time.time()
filename = f"osxphotos-export-2-test-{timestamp}.jpg" filename = f"osxphotos-export-2-test-{timestamp}.jpg"
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename) got_dest = photos[0].export(dest, filename)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
assert os.path.isfile(got_dest) assert os.path.isfile(got_dest)
# remove the temporary file
os.remove(got_dest)
def test_export_3(): def test_export_3():
# test file already exists and test increment=True (default) # test file already exists and test increment=True (default)
@@ -464,7 +460,8 @@ def test_export_3():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
@@ -473,16 +470,12 @@ def test_export_3():
filename2 = f"{filename2.stem} (1){filename2.suffix}" filename2 = f"{filename2.stem} (1){filename2.suffix}"
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
got_dest = photos[0].export(dest) got_dest = photos[0].export(dest)[0]
got_dest_2 = photos[0].export(dest) got_dest_2 = photos[0].export(dest)[0]
assert got_dest_2 == expected_dest_2 assert got_dest_2 == expected_dest_2
assert os.path.isfile(got_dest_2) assert os.path.isfile(got_dest_2)
# remove the temporary file
os.remove(got_dest)
os.remove(got_dest_2)
def test_export_4(): def test_export_4():
# test user supplied file already exists and test increment=True (default) # test user supplied file already exists and test increment=True (default)
@@ -494,7 +487,8 @@ def test_export_4():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
@@ -503,16 +497,12 @@ def test_export_4():
filename2 = f"osxphotos-export-2-test-{timestamp} (1).jpg" filename2 = f"osxphotos-export-2-test-{timestamp} (1).jpg"
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
got_dest = photos[0].export(dest, filename) got_dest = photos[0].export(dest, filename)[0]
got_dest_2 = photos[0].export(dest, filename) got_dest_2 = photos[0].export(dest, filename)[0]
assert got_dest_2 == expected_dest_2 assert got_dest_2 == expected_dest_2
assert os.path.isfile(got_dest_2) assert os.path.isfile(got_dest_2)
# remove the temporary file
os.remove(got_dest)
os.remove(got_dest_2)
def test_export_5(): def test_export_5():
# test file already exists and test increment=True (default) # test file already exists and test increment=True (default)
@@ -523,23 +513,21 @@ def test_export_5():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest) got_dest = photos[0].export(dest)[0]
got_dest_2 = photos[0].export(dest, overwrite=True) got_dest_2 = photos[0].export(dest, overwrite=True)[0]
assert got_dest_2 == got_dest assert got_dest_2 == got_dest
assert got_dest_2 == expected_dest assert got_dest_2 == expected_dest
assert os.path.isfile(got_dest_2) assert os.path.isfile(got_dest_2)
# remove the temporary file
os.remove(got_dest)
def test_export_6(): def test_export_6():
# test user supplied file already exists and test increment=True (default) # test user supplied file already exists and test increment=True (default)
@@ -552,7 +540,8 @@ def test_export_6():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
@@ -560,16 +549,13 @@ def test_export_6():
filename = f"osxphotos-export-test-{timestamp}.jpg" filename = f"osxphotos-export-test-{timestamp}.jpg"
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename) got_dest = photos[0].export(dest, filename)[0]
got_dest_2 = photos[0].export(dest, filename, overwrite=True) got_dest_2 = photos[0].export(dest, filename, overwrite=True)[0]
assert got_dest_2 == got_dest assert got_dest_2 == got_dest
assert got_dest_2 == expected_dest assert got_dest_2 == expected_dest
assert os.path.isfile(got_dest_2) assert os.path.isfile(got_dest_2)
# remove the temporary file
os.remove(got_dest)
def test_export_7(): def test_export_7():
# test file already exists and test increment=False (not default), overwrite=False (default) # test file already exists and test increment=False (not default), overwrite=False (default)
@@ -580,21 +566,19 @@ def test_export_7():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].filename
got_dest = photos[0].export(dest) got_dest = photos[0].export(dest)[0]
with pytest.raises(Exception) as e: with pytest.raises(Exception) as e:
# try to export again with increment = False # try to export again with increment = False
assert photos[0].export(dest, increment=False) assert photos[0].export(dest, increment=False)
assert e.type == type(FileExistsError()) assert e.type == type(FileExistsError())
# remove the temporary file
os.remove(got_dest)
def test_export_8(): def test_export_8():
# try to export missing file # try to export missing file
@@ -605,14 +589,15 @@ def test_export_8():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["missing"]]) photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
filename = photos[0].filename filename = photos[0].filename
with pytest.raises(Exception) as e: with pytest.raises(Exception) as e:
assert photos[0].export(dest) assert photos[0].export(dest)[0]
assert e.type == type(FileNotFoundError()) assert e.type == type(FileNotFoundError())
@@ -625,15 +610,16 @@ def test_export_9():
import osxphotos import osxphotos
dest = tempfile.gettempdir()
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
filename = photos[0].filename filename = photos[0].filename
with pytest.raises(Exception) as e: with pytest.raises(Exception) as e:
assert photos[0].export(dest, edited=True) assert photos[0].export(dest, edited=True)
assert e.type == type(FileNotFoundError()) assert e.type == ValueError
def test_export_10(): def test_export_10():
@@ -646,8 +632,9 @@ def test_export_10():
import osxphotos import osxphotos
dest = tempfile.gettempdir()
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
timestamp = time.time() timestamp = time.time()
@@ -655,7 +642,7 @@ def test_export_10():
with pytest.raises(Exception) as e: with pytest.raises(Exception) as e:
assert photos[0].export(dest, filename, edited=True) assert photos[0].export(dest, filename, edited=True)
assert e.type == type(FileNotFoundError()) assert e.type == ValueError
def test_export_11(): def test_export_11():
@@ -667,7 +654,8 @@ def test_export_11():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
@@ -675,12 +663,9 @@ def test_export_11():
filename = f"osxphotos-export-test-{timestamp}.jpg" filename = f"osxphotos-export-test-{timestamp}.jpg"
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename, edited=True) got_dest = photos[0].export(dest, filename, edited=True)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
# remove the temporary file
os.remove(got_dest)
def test_export_12(): def test_export_12():
# export edited file with default name # export edited file with default name
@@ -691,7 +676,8 @@ def test_export_12():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
@@ -700,12 +686,9 @@ def test_export_12():
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True) got_dest = photos[0].export(dest, edited=True)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
# remove the temporary file
os.remove(got_dest)
def test_export_13(): def test_export_13():
# export to invalid destination # export to invalid destination
@@ -716,7 +699,8 @@ def test_export_13():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
# create a folder that doesn't exist # create a folder that doesn't exist
i = 0 i = 0

View File

@@ -67,20 +67,18 @@ def test_export_1():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest) got_dest = photos[0].export(dest)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
assert os.path.isfile(got_dest) assert os.path.isfile(got_dest)
# remove the temporary file
os.remove(got_dest)
def test_export_2(): def test_export_2():
# test export with user provided filename # test export with user provided filename
@@ -91,21 +89,19 @@ def test_export_2():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
timestamp = time.time() timestamp = time.time()
filename = f"osxphotos-export-2-test-{timestamp}.jpg" filename = f"osxphotos-export-2-test-{timestamp}.jpg"
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename) got_dest = photos[0].export(dest, filename)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
assert os.path.isfile(got_dest) assert os.path.isfile(got_dest)
# remove the temporary file
os.remove(got_dest)
def test_export_3(): def test_export_3():
# test file already exists and test increment=True (default) # test file already exists and test increment=True (default)
@@ -116,7 +112,8 @@ def test_export_3():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
@@ -126,16 +123,12 @@ def test_export_3():
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
got_dest = photos[0].export(dest) got_dest = photos[0].export(dest)[0]
got_dest_2 = photos[0].export(dest) got_dest_2 = photos[0].export(dest)[0]
assert got_dest_2 == expected_dest_2 assert got_dest_2 == expected_dest_2
assert os.path.isfile(got_dest_2) assert os.path.isfile(got_dest_2)
# remove the temporary file
os.remove(got_dest)
os.remove(got_dest_2)
def test_export_4(): def test_export_4():
# test user supplied file already exists and test increment=True (default) # test user supplied file already exists and test increment=True (default)
@@ -147,7 +140,8 @@ def test_export_4():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
@@ -157,16 +151,12 @@ def test_export_4():
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
got_dest = photos[0].export(dest, filename) got_dest = photos[0].export(dest, filename)[0]
got_dest_2 = photos[0].export(dest, filename) got_dest_2 = photos[0].export(dest, filename)[0]
assert got_dest_2 == expected_dest_2 assert got_dest_2 == expected_dest_2
assert os.path.isfile(got_dest_2) assert os.path.isfile(got_dest_2)
# remove the temporary file
os.remove(got_dest)
os.remove(got_dest_2)
def test_export_5(): def test_export_5():
# test file already exists and test increment=True (default) # test file already exists and test increment=True (default)
@@ -177,23 +167,21 @@ def test_export_5():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest) got_dest = photos[0].export(dest)[0]
got_dest_2 = photos[0].export(dest, overwrite=True) got_dest_2 = photos[0].export(dest, overwrite=True)[0]
assert got_dest_2 == got_dest assert got_dest_2 == got_dest
assert got_dest_2 == expected_dest assert got_dest_2 == expected_dest
assert os.path.isfile(got_dest_2) assert os.path.isfile(got_dest_2)
# remove the temporary file
os.remove(got_dest)
def test_export_6(): def test_export_6():
# test user supplied file already exists and test increment=True (default) # test user supplied file already exists and test increment=True (default)
@@ -206,7 +194,8 @@ def test_export_6():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
@@ -214,16 +203,13 @@ def test_export_6():
filename = f"osxphotos-export-test-{timestamp}.jpg" filename = f"osxphotos-export-test-{timestamp}.jpg"
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename) got_dest = photos[0].export(dest, filename)[0]
got_dest_2 = photos[0].export(dest, filename, overwrite=True) got_dest_2 = photos[0].export(dest, filename, overwrite=True)[0]
assert got_dest_2 == got_dest assert got_dest_2 == got_dest
assert got_dest_2 == expected_dest assert got_dest_2 == expected_dest
assert os.path.isfile(got_dest_2) assert os.path.isfile(got_dest_2)
# remove the temporary file
os.remove(got_dest)
def test_export_7(): def test_export_7():
# test file already exists and test increment=False (not default), overwrite=False (default) # test file already exists and test increment=False (not default), overwrite=False (default)
@@ -234,22 +220,20 @@ def test_export_7():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest) got_dest = photos[0].export(dest)[0]
with pytest.raises(Exception) as e: with pytest.raises(Exception) as e:
# try to export again with increment = False # try to export again with increment = False
assert photos[0].export(dest, increment=False) assert photos[0].export(dest, increment=False)
assert e.type == type(FileExistsError()) assert e.type == type(FileExistsError())
# remove the temporary file
os.remove(got_dest)
def test_export_8(): def test_export_8():
# try to export missing file # try to export missing file
@@ -260,7 +244,8 @@ def test_export_8():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["missing"]]) photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
@@ -281,16 +266,14 @@ def test_export_9():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
with pytest.raises(Exception) as e: with pytest.raises(Exception) as e:
assert photos[0].export(dest, edited=True) assert photos[0].export(dest, edited=True)
assert e.type == type(FileNotFoundError()) assert e.type == ValueError
def test_export_10(): def test_export_10():
@@ -303,7 +286,8 @@ def test_export_10():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
@@ -313,7 +297,7 @@ def test_export_10():
with pytest.raises(Exception) as e: with pytest.raises(Exception) as e:
assert photos[0].export(dest, filename, edited=True) assert photos[0].export(dest, filename, edited=True)
assert e.type == type(FileNotFoundError()) assert e.type == ValueError
def test_export_11(): def test_export_11():
@@ -325,7 +309,8 @@ def test_export_11():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
@@ -333,12 +318,9 @@ def test_export_11():
filename = f"osxphotos-export-test-{timestamp}.jpg" filename = f"osxphotos-export-test-{timestamp}.jpg"
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename, edited=True) got_dest = photos[0].export(dest, filename, edited=True)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
# remove the temporary file
os.remove(got_dest)
def test_export_12(): def test_export_12():
# export edited file with default name # export edited file with default name
@@ -349,7 +331,8 @@ def test_export_12():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
@@ -358,12 +341,9 @@ def test_export_12():
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True) got_dest = photos[0].export(dest, edited=True)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
# remove the temporary file
os.remove(got_dest)
def test_export_13(): def test_export_13():
# export to invalid destination # export to invalid destination
@@ -374,7 +354,8 @@ def test_export_13():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
# create a folder that doesn't exist # create a folder that doesn't exist
i = 0 i = 0
@@ -446,8 +427,7 @@ def test_exiftool_json_sidecar():
json_expected = json.loads( json_expected = json.loads(
""" """
[{"File:FileName": "DC99FBDD-7A52-4100-A5BB-344131646C30.jpeg", [{"XMP:Title": "St. James\'s Park",
"XMP:Title": "St. James\'s Park",
"XMP:TagsList": ["London 2018", "St. James\'s Park", "England", "United Kingdom", "UK", "London"], "XMP:TagsList": ["London 2018", "St. James\'s Park", "England", "United Kingdom", "UK", "London"],
"IPTC:Keywords": ["London 2018", "St. James\'s Park", "England", "United Kingdom", "UK", "London"], "IPTC:Keywords": ["London 2018", "St. James\'s Park", "England", "United Kingdom", "UK", "London"],
"XMP:Subject": ["London 2018", "St. James\'s Park", "England", "United Kingdom", "UK", "London"], "XMP:Subject": ["London 2018", "St. James\'s Park", "England", "United Kingdom", "UK", "London"],

View File

@@ -0,0 +1,158 @@
import os
import pytest
from osxphotos._constants import _UNKNOWN_PERSON
skip_test = False if "OSXPHOTOS_TEST_EXPORT" in os.environ else True
pytestmark = pytest.mark.skipif(
skip_test, reason="These tests only run against system photos library"
)
PHOTOS_DB = "/Users/rhet/Pictures/Photos Library.photoslibrary"
UUID_DICT = {
"has_adjustments": "A8111956-E900-4DEC-9191-A04A87C07BC5",
"no_adjustments": "EA7BB55F-92F1-4818-94E3-E8DEDC6B2E31",
"live": "9032C168-9319-40C0-8210-5ADC42F4C603",
}
@pytest.fixture(scope="module")
def photosdb():
import osxphotos
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
return photosdb
def test_export_default_name(photosdb):
# test basic export
# get an unedited image and export it using default filename
import os
import os.path
import tempfile
import osxphotos
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, use_photos_export=True)[0]
assert got_dest == expected_dest
assert os.path.isfile(got_dest)
def test_export_supplied_name(photosdb):
# test export with user provided filename
import os
import os.path
import tempfile
import time
import osxphotos
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
timestamp = time.time()
filename = f"osxphotos-export-2-test-{timestamp}.jpeg"
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename, use_photos_export=True)[0]
assert got_dest == expected_dest
assert os.path.isfile(got_dest)
def test_export_edited(photosdb):
# test export edited file
import os
import os.path
import pathlib
import tempfile
import osxphotos
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
suffix = pathlib.Path(photos[0].path_edited).suffix
filename = f"{pathlib.Path(photos[0].filename).stem}_edited{suffix}"
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, use_photos_export=True, edited=True)[0]
assert got_dest == expected_dest
assert os.path.isfile(expected_dest)
def test_export_edited_exiftool(photosdb):
# test export edited file
import os
import os.path
import pathlib
import tempfile
import osxphotos
import osxphotos.exiftool
import logging
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
got_dest = photos[0].export(
dest, use_photos_export=True, edited=True, exiftool=True
)
logging.warning(got_dest)
got_dest = got_dest[0]
assert os.path.isfile(got_dest)
exif = osxphotos.exiftool.ExifTool(got_dest)
assert exif.data["IPTC:Keywords"] == "osxphotos"
def test_export_edited_supplied_name(photosdb):
# test export with user provided filename
import os
import os.path
import tempfile
import time
import osxphotos
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
timestamp = time.time()
filename = f"osxphotos-export-2-test-{timestamp}.jpeg"
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename, use_photos_export=True, edited=True)[0]
assert got_dest == expected_dest
assert os.path.isfile(got_dest)
def test_export_edited_no_edit(photosdb):
# test export edited file if not actually edited
import os
import os.path
import pathlib
import tempfile
import osxphotos
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
with pytest.raises(Exception) as e:
assert photos[0].export(dest, use_photos_export=True, edited=True)
assert e.type == ValueError

View File

@@ -55,20 +55,18 @@ def test_export_1():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest) got_dest = photos[0].export(dest)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
assert os.path.isfile(got_dest) assert os.path.isfile(got_dest)
# remove the temporary file
os.remove(got_dest)
def test_export_2(): def test_export_2():
# test export with user provided filename # test export with user provided filename
@@ -79,21 +77,19 @@ def test_export_2():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
timestamp = time.time() timestamp = time.time()
filename = f"osxphotos-export-2-test-{timestamp}.jpg" filename = f"osxphotos-export-2-test-{timestamp}.jpg"
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename) got_dest = photos[0].export(dest, filename)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
assert os.path.isfile(got_dest) assert os.path.isfile(got_dest)
# remove the temporary file
os.remove(got_dest)
def test_export_3(): def test_export_3():
# test file already exists and test increment=True (default) # test file already exists and test increment=True (default)
@@ -104,7 +100,8 @@ def test_export_3():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
@@ -114,16 +111,12 @@ def test_export_3():
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
got_dest = photos[0].export(dest) got_dest = photos[0].export(dest)[0]
got_dest_2 = photos[0].export(dest) got_dest_2 = photos[0].export(dest)[0]
assert got_dest_2 == expected_dest_2 assert got_dest_2 == expected_dest_2
assert os.path.isfile(got_dest_2) assert os.path.isfile(got_dest_2)
# remove the temporary file
os.remove(got_dest)
os.remove(got_dest_2)
def test_export_4(): def test_export_4():
# test user supplied file already exists and test increment=True (default) # test user supplied file already exists and test increment=True (default)
@@ -135,7 +128,8 @@ def test_export_4():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
@@ -145,16 +139,12 @@ def test_export_4():
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
expected_dest_2 = os.path.join(dest, filename2) expected_dest_2 = os.path.join(dest, filename2)
got_dest = photos[0].export(dest, filename) got_dest = photos[0].export(dest, filename)[0]
got_dest_2 = photos[0].export(dest, filename) got_dest_2 = photos[0].export(dest, filename)[0]
assert got_dest_2 == expected_dest_2 assert got_dest_2 == expected_dest_2
assert os.path.isfile(got_dest_2) assert os.path.isfile(got_dest_2)
# remove the temporary file
os.remove(got_dest)
os.remove(got_dest_2)
def test_export_5(): def test_export_5():
# test file already exists and test increment=True (default) # test file already exists and test increment=True (default)
@@ -165,23 +155,21 @@ def test_export_5():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest) got_dest = photos[0].export(dest)[0]
got_dest_2 = photos[0].export(dest, overwrite=True) got_dest_2 = photos[0].export(dest, overwrite=True)[0]
assert got_dest_2 == got_dest assert got_dest_2 == got_dest
assert got_dest_2 == expected_dest assert got_dest_2 == expected_dest
assert os.path.isfile(got_dest_2) assert os.path.isfile(got_dest_2)
# remove the temporary file
os.remove(got_dest)
def test_export_6(): def test_export_6():
# test user supplied file already exists and test increment=True (default) # test user supplied file already exists and test increment=True (default)
@@ -194,7 +182,8 @@ def test_export_6():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
@@ -202,16 +191,13 @@ def test_export_6():
filename = f"osxphotos-export-test-{timestamp}.jpg" filename = f"osxphotos-export-test-{timestamp}.jpg"
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename) got_dest = photos[0].export(dest, filename)[0]
got_dest_2 = photos[0].export(dest, filename, overwrite=True) got_dest_2 = photos[0].export(dest, filename, overwrite=True)[0]
assert got_dest_2 == got_dest assert got_dest_2 == got_dest
assert got_dest_2 == expected_dest assert got_dest_2 == expected_dest
assert os.path.isfile(got_dest_2) assert os.path.isfile(got_dest_2)
# remove the temporary file
os.remove(got_dest)
def test_export_7(): def test_export_7():
# test file already exists and test increment=False (not default), overwrite=False (default) # test file already exists and test increment=False (not default), overwrite=False (default)
@@ -222,22 +208,20 @@ def test_export_7():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]]) photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename filename = photos[0].filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest) got_dest = photos[0].export(dest)[0]
with pytest.raises(Exception) as e: with pytest.raises(Exception) as e:
# try to export again with increment = False # try to export again with increment = False
assert photos[0].export(dest, increment=False) assert photos[0].export(dest, increment=False)[0]
assert e.type == type(FileExistsError()) assert e.type == type(FileExistsError())
# remove the temporary file
os.remove(got_dest)
def test_export_8(): def test_export_8():
# try to export missing file # try to export missing file
@@ -248,7 +232,8 @@ def test_export_8():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["missing"]]) photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
@@ -256,7 +241,7 @@ def test_export_8():
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
with pytest.raises(Exception) as e: with pytest.raises(Exception) as e:
assert photos[0].export(dest) assert photos[0].export(dest)[0]
assert e.type == type(FileNotFoundError()) assert e.type == type(FileNotFoundError())
@@ -269,7 +254,8 @@ def test_export_9():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
@@ -278,7 +264,7 @@ def test_export_9():
with pytest.raises(Exception) as e: with pytest.raises(Exception) as e:
assert photos[0].export(dest, edited=True) assert photos[0].export(dest, edited=True)
assert e.type == type(FileNotFoundError()) assert e.type == ValueError
def test_export_10(): def test_export_10():
@@ -291,7 +277,8 @@ def test_export_10():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
@@ -300,8 +287,8 @@ def test_export_10():
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
with pytest.raises(Exception) as e: with pytest.raises(Exception) as e:
assert photos[0].export(dest, filename, edited=True) assert photos[0].export(dest, filename, edited=True)[0]
assert e.type == type(FileNotFoundError()) assert e.type == ValueError
def test_export_11(): def test_export_11():
@@ -313,7 +300,8 @@ def test_export_11():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
@@ -321,12 +309,9 @@ def test_export_11():
filename = f"osxphotos-export-test-{timestamp}.jpg" filename = f"osxphotos-export-test-{timestamp}.jpg"
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename, edited=True) got_dest = photos[0].export(dest, filename, edited=True)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
# remove the temporary file
os.remove(got_dest)
def test_export_12(): def test_export_12():
# export edited file with default name # export edited file with default name
@@ -337,7 +322,8 @@ def test_export_12():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
@@ -346,12 +332,9 @@ def test_export_12():
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True) got_dest = photos[0].export(dest, edited=True)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
# remove the temporary file
os.remove(got_dest)
def test_export_13(): def test_export_13():
# export to invalid destination # export to invalid destination
@@ -362,7 +345,8 @@ def test_export_13():
import osxphotos import osxphotos
dest = tempfile.gettempdir() tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dest = tempdir.name
# create a folder that doesn't exist # create a folder that doesn't exist
i = 0 i = 0
@@ -377,7 +361,7 @@ def test_export_13():
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
with pytest.raises(Exception) as e: with pytest.raises(Exception) as e:
assert photos[0].export(dest) assert photos[0].export(dest)[0]
assert e.type == type(FileNotFoundError()) assert e.type == type(FileNotFoundError())
@@ -390,8 +374,7 @@ def test_exiftool_json_sidecar():
json_expected = json.loads( json_expected = json.loads(
""" """
[{"File:FileName": "St James Park.jpg", [{"XMP:Title": "St. James\'s Park",
"XMP:Title": "St. James\'s Park",
"XMP:TagsList": ["London 2018", "St. James\'s Park", "England", "United Kingdom", "UK", "London"], "XMP:TagsList": ["London 2018", "St. James\'s Park", "England", "United Kingdom", "UK", "London"],
"IPTC:Keywords": ["London 2018", "St. James\'s Park", "England", "United Kingdom", "UK", "London"], "IPTC:Keywords": ["London 2018", "St. James\'s Park", "England", "United Kingdom", "UK", "London"],
"XMP:Subject": ["London 2018", "St. James\'s Park", "England", "United Kingdom", "UK", "London"], "XMP:Subject": ["London 2018", "St. James\'s Park", "England", "United Kingdom", "UK", "London"],

View File

@@ -31,7 +31,7 @@ def test_export_1():
filename = photos[0].filename filename = photos[0].filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest) got_dest = photos[0].export(dest)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
assert os.path.isfile(got_dest) assert os.path.isfile(got_dest)
@@ -55,7 +55,7 @@ def test_export_2():
filename = photos[0].original_filename filename = photos[0].original_filename
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename) got_dest = photos[0].export(dest, filename)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
assert os.path.isfile(got_dest) assert os.path.isfile(got_dest)
@@ -81,7 +81,7 @@ def test_export_edited_name():
filename = f"osxphotos-export-test-{timestamp}.jpg" filename = f"osxphotos-export-test-{timestamp}.jpg"
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename, edited=True) got_dest = photos[0].export(dest, filename, edited=True)[0]
assert got_dest == expected_dest assert got_dest == expected_dest
assert pathlib.Path(got_dest).name == filename assert pathlib.Path(got_dest).name == filename
@@ -100,7 +100,7 @@ def test_export_edited_default():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
got_dest = photos[0].export(dest, edited=True) got_dest = photos[0].export(dest, edited=True)[0]
assert pathlib.Path(got_dest).name == FILENAME_DICT["current_edited"] assert pathlib.Path(got_dest).name == FILENAME_DICT["current_edited"]
@@ -125,7 +125,7 @@ def test_export_edited_wrong_suffix(caplog):
filename = f"osxphotos-export-test-{timestamp}.cr2" filename = f"osxphotos-export-test-{timestamp}.cr2"
expected_dest = os.path.join(dest, filename) expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, filename, edited=True) got_dest = photos[0].export(dest, filename, edited=True)[0]
assert "Invalid destination suffix" in caplog.text assert "Invalid destination suffix" in caplog.text
assert got_dest == expected_dest assert got_dest == expected_dest
assert pathlib.Path(got_dest).name == filename assert pathlib.Path(got_dest).name == filename

View File

@@ -46,9 +46,8 @@ def test_export_live_1():
filename = photos[0].filename filename = photos[0].filename
expected_dest = os.path.join(dest.name, filename) expected_dest = os.path.join(dest.name, filename)
got_dest = photos[0].export(dest.name, live_photo=True) got_dest = photos[0].export(dest.name, live_photo=True)[0]
got_movie = f"{pathlib.Path(got_dest).parent / pathlib.Path(got_dest).stem}.mov" got_movie = f"{pathlib.Path(got_dest).parent / pathlib.Path(got_dest).stem}.mov"
expected_dest = os.path.join(dest.name, filename)
files = glob.glob(os.path.join(dest.name, "*")) files = glob.glob(os.path.join(dest.name, "*"))
assert len(files) == 2 assert len(files) == 2
@@ -73,7 +72,7 @@ def test_export_live_2():
filename = photos[0].filename filename = photos[0].filename
expected_dest = os.path.join(dest.name, filename) expected_dest = os.path.join(dest.name, filename)
got_dest = photos[0].export(dest.name, live_photo=False) got_dest = photos[0].export(dest.name, live_photo=False)[0]
got_movie = f"{pathlib.Path(got_dest).parent / pathlib.Path(got_dest).stem}.mov" got_movie = f"{pathlib.Path(got_dest).parent / pathlib.Path(got_dest).stem}.mov"
files = glob.glob(os.path.join(dest.name, "*")) files = glob.glob(os.path.join(dest.name, "*"))
@@ -83,6 +82,34 @@ def test_export_live_2():
assert got_movie not in files assert got_movie not in files
def test_export_live_3():
# export a live photo and associated .mov,
# check list return of export
import glob
import os.path
import pathlib
import tempfile
import osxphotos
dest = tempfile.TemporaryDirectory(prefix="osxphotos_")
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["live"]])
filename = photos[0].filename
expected_dest = os.path.join(dest.name, filename)
expected_mov = f"{dest.name}/{pathlib.Path(expected_dest).stem}.mov"
got_files = photos[0].export(dest.name, live_photo=True)
# got_dest = got_files[0]
# got_movie = f"{pathlib.Path(got_dest).parent / pathlib.Path(got_dest).stem}.mov"
# files = glob.glob(os.path.join(dest.name, "*"))
assert len(got_files) == 2
assert expected_dest in got_files
assert expected_mov in got_files
# def test_export_live_3(): # def test_export_live_3():
# # export a live photo and associated .mov and edited file # # export a live photo and associated .mov and edited file
# import glob # import glob