Added tests, fixed bug in export_db
This commit is contained in:
@@ -1236,6 +1236,15 @@ def query(
|
|||||||
help="Convert all non-jpeg images (e.g. RAW, HEIC, PNG, etc) "
|
help="Convert all non-jpeg images (e.g. RAW, HEIC, PNG, etc) "
|
||||||
"to JPEG upon export.",
|
"to JPEG upon export.",
|
||||||
)
|
)
|
||||||
|
@click.option(
|
||||||
|
"--jpeg-quality",
|
||||||
|
type=click.FloatRange(0.0, 1.0),
|
||||||
|
default=1.0,
|
||||||
|
help="Value in range 0.0 to 1.0 to use with --convert-to-jpeg. "
|
||||||
|
"A value of 1.0 specifies best quality, "
|
||||||
|
"a value of 0.0 specifies maximum compression. "
|
||||||
|
"Defaults to 1.0."
|
||||||
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"--sidecar",
|
"--sidecar",
|
||||||
default=None,
|
default=None,
|
||||||
@@ -1356,6 +1365,7 @@ def export(
|
|||||||
description_template,
|
description_template,
|
||||||
current_name,
|
current_name,
|
||||||
convert_to_jpeg,
|
convert_to_jpeg,
|
||||||
|
jpeg_quality,
|
||||||
sidecar,
|
sidecar,
|
||||||
only_photos,
|
only_photos,
|
||||||
only_movies,
|
only_movies,
|
||||||
@@ -1628,6 +1638,7 @@ def export(
|
|||||||
edited_suffix=edited_suffix,
|
edited_suffix=edited_suffix,
|
||||||
use_photos_export=use_photos_export,
|
use_photos_export=use_photos_export,
|
||||||
convert_to_jpeg=convert_to_jpeg,
|
convert_to_jpeg=convert_to_jpeg,
|
||||||
|
jpeg_quality=jpeg_quality,
|
||||||
)
|
)
|
||||||
results_exported.extend(results.exported)
|
results_exported.extend(results.exported)
|
||||||
results_new.extend(results.new)
|
results_new.extend(results.new)
|
||||||
@@ -1676,6 +1687,7 @@ def export(
|
|||||||
edited_suffix=edited_suffix,
|
edited_suffix=edited_suffix,
|
||||||
use_photos_export=use_photos_export,
|
use_photos_export=use_photos_export,
|
||||||
convert_to_jpeg=convert_to_jpeg,
|
convert_to_jpeg=convert_to_jpeg,
|
||||||
|
jpeg_quality=jpeg_quality,
|
||||||
)
|
)
|
||||||
results_exported.extend(results.exported)
|
results_exported.extend(results.exported)
|
||||||
results_new.extend(results.new)
|
results_new.extend(results.new)
|
||||||
@@ -2167,6 +2179,7 @@ def export_photo(
|
|||||||
edited_suffix="_edited",
|
edited_suffix="_edited",
|
||||||
use_photos_export=False,
|
use_photos_export=False,
|
||||||
convert_to_jpeg=False,
|
convert_to_jpeg=False,
|
||||||
|
jpeg_quality=1.0,
|
||||||
):
|
):
|
||||||
""" Helper function for export that does the actual export
|
""" Helper function for export that does the actual export
|
||||||
|
|
||||||
@@ -2199,6 +2212,7 @@ def export_photo(
|
|||||||
touch_file: boolean; sets file's modification time to match photo date
|
touch_file: boolean; sets file's modification time to match photo date
|
||||||
use_photos_export: boolean; if True forces the use of AppleScript to export even if photo not missing
|
use_photos_export: boolean; if True forces the use of AppleScript to export even if photo not missing
|
||||||
convert_to_jpeg: boolean; if True, converts non-jpeg images to jpeg
|
convert_to_jpeg: boolean; if True, converts non-jpeg images to jpeg
|
||||||
|
jpeg_quality: float in range 0.0 <= jpeg_quality <= 1.0. A value of 1.0 specifies use best quality, a value of 0.0 specifies use maximum compression.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list of path(s) of exported photo or None if photo was missing
|
list of path(s) of exported photo or None if photo was missing
|
||||||
@@ -2286,6 +2300,7 @@ def export_photo(
|
|||||||
dry_run=dry_run,
|
dry_run=dry_run,
|
||||||
touch_file=touch_file,
|
touch_file=touch_file,
|
||||||
convert_to_jpeg=convert_to_jpeg,
|
convert_to_jpeg=convert_to_jpeg,
|
||||||
|
jpeg_quality=jpeg_quality,
|
||||||
)
|
)
|
||||||
|
|
||||||
results_exported.extend(export_results.exported)
|
results_exported.extend(export_results.exported)
|
||||||
@@ -2346,6 +2361,7 @@ def export_photo(
|
|||||||
dry_run=dry_run,
|
dry_run=dry_run,
|
||||||
touch_file=touch_file,
|
touch_file=touch_file,
|
||||||
convert_to_jpeg=convert_to_jpeg,
|
convert_to_jpeg=convert_to_jpeg,
|
||||||
|
jpeg_quality=jpeg_quality,
|
||||||
)
|
)
|
||||||
|
|
||||||
results_exported.extend(export_results_edited.exported)
|
results_exported.extend(export_results_edited.exported)
|
||||||
|
|||||||
@@ -94,6 +94,11 @@ class ExportDB_ABC(ABC):
|
|||||||
class ExportDBNoOp(ExportDB_ABC):
|
class ExportDBNoOp(ExportDB_ABC):
|
||||||
""" An ExportDB with NoOp methods """
|
""" An ExportDB with NoOp methods """
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.was_created = True
|
||||||
|
self.was_upgraded = False
|
||||||
|
self.version = OSXPHOTOS_EXPORTDB_VERSION
|
||||||
|
|
||||||
def get_uuid_for_file(self, filename):
|
def get_uuid_for_file(self, filename):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -441,22 +446,16 @@ class ExportDB(ExportDB_ABC):
|
|||||||
raise ValueError(f"expected 3 elements for stat, got {len(stats)}")
|
raise ValueError(f"expected 3 elements for stat, got {len(stats)}")
|
||||||
|
|
||||||
conn = self._conn
|
conn = self._conn
|
||||||
try:
|
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute(
|
c.execute(
|
||||||
f"UPDATE {table} "
|
f"INSERT OR REPLACE INTO {table}(filepath_normalized, mode, size, mtime) VALUES (?, ?, ?, ?);",
|
||||||
+ "SET converted_mode = ?, converted_size = ?, converted_mtime = ? "
|
(filename, *stats),
|
||||||
+ "WHERE filepath_normalized = ?;",
|
|
||||||
(*stats, filename),
|
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
except Error as e:
|
|
||||||
logging.warning(e)
|
|
||||||
|
|
||||||
def _get_stat_for_file(self, table, filename):
|
def _get_stat_for_file(self, table, filename):
|
||||||
filename = str(pathlib.Path(filename).relative_to(self._path)).lower()
|
filename = str(pathlib.Path(filename).relative_to(self._path)).lower()
|
||||||
conn = self._conn
|
conn = self._conn
|
||||||
try:
|
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute(
|
c.execute(
|
||||||
f"SELECT mode, size, mtime FROM {table} WHERE filepath_normalized = ?",
|
f"SELECT mode, size, mtime FROM {table} WHERE filepath_normalized = ?",
|
||||||
@@ -469,9 +468,6 @@ class ExportDB(ExportDB_ABC):
|
|||||||
stats = (stats[0], stats[1], mtime)
|
stats = (stats[0], stats[1], mtime)
|
||||||
else:
|
else:
|
||||||
stats = (None, None, None)
|
stats = (None, None, None)
|
||||||
except Error as e:
|
|
||||||
logging.warning(e)
|
|
||||||
stats = (None, None, None)
|
|
||||||
|
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
@@ -636,7 +632,6 @@ class ExportDBInMemory(ExportDB):
|
|||||||
|
|
||||||
def _open_export_db(self, dbfile):
|
def _open_export_db(self, dbfile):
|
||||||
""" open export database and return a db connection
|
""" open export database and return a db connection
|
||||||
if dbfile does not exist, will create and initialize the database
|
|
||||||
returns: connection to the database
|
returns: connection to the database
|
||||||
"""
|
"""
|
||||||
if not os.path.isfile(dbfile):
|
if not os.path.isfile(dbfile):
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ class FileUtilMacOS(FileUtilABC):
|
|||||||
Args:
|
Args:
|
||||||
src_file: image file to convert
|
src_file: image file to convert
|
||||||
dest_file: destination path to write converted file to
|
dest_file: destination path to write converted file to
|
||||||
compression quality: JPEG compression quality in range 0.0 <= compression_quality <= 1.0; default 1.0
|
compression quality: JPEG compression quality in range 0.0 <= compression_quality <= 1.0; default 1.0 (best quality)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if success, otherwise False
|
True if success, otherwise False
|
||||||
|
|||||||
@@ -307,6 +307,7 @@ def export2(
|
|||||||
dry_run=False,
|
dry_run=False,
|
||||||
touch_file=False,
|
touch_file=False,
|
||||||
convert_to_jpeg=False,
|
convert_to_jpeg=False,
|
||||||
|
jpeg_quality=1.0,
|
||||||
):
|
):
|
||||||
""" export photo, like export but with update and dry_run options
|
""" export photo, like export but with update and dry_run options
|
||||||
dest: must be valid destination path or exception raised
|
dest: must be valid destination path or exception raised
|
||||||
@@ -348,6 +349,7 @@ def export2(
|
|||||||
dry_run: (boolean, default=False); set to True to run in "dry run" mode
|
dry_run: (boolean, default=False); set to True to run in "dry run" mode
|
||||||
touch_file: (boolean, default=False); if True, sets file's modification time upon photo date
|
touch_file: (boolean, default=False); if True, sets file's modification time upon photo date
|
||||||
convert_to_jpeg: boolean; if True, converts non-jpeg images to jpeg
|
convert_to_jpeg: boolean; if True, converts non-jpeg images to jpeg
|
||||||
|
jpeg_quality: float in range 0.0 <= jpeg_quality <= 1.0. A value of 1.0 specifies use best quality, a value of 0.0 specifies use maximum compression.
|
||||||
|
|
||||||
Returns: ExportResults namedtuple with fields: exported, new, updated, skipped
|
Returns: ExportResults namedtuple with fields: exported, new, updated, skipped
|
||||||
where each field is a list of file paths
|
where each field is a list of file paths
|
||||||
@@ -562,6 +564,7 @@ def export2(
|
|||||||
convert_to_jpeg,
|
convert_to_jpeg,
|
||||||
fileutil=fileutil,
|
fileutil=fileutil,
|
||||||
edited=edited,
|
edited=edited,
|
||||||
|
jpeg_quality=jpeg_quality,
|
||||||
)
|
)
|
||||||
exported_files = results.exported
|
exported_files = results.exported
|
||||||
update_new_files = results.new
|
update_new_files = results.new
|
||||||
@@ -590,6 +593,7 @@ def export2(
|
|||||||
touch_file,
|
touch_file,
|
||||||
convert_to_jpeg,
|
convert_to_jpeg,
|
||||||
fileutil=fileutil,
|
fileutil=fileutil,
|
||||||
|
jpeg_quality=jpeg_quality,
|
||||||
)
|
)
|
||||||
exported_files.extend(results.exported)
|
exported_files.extend(results.exported)
|
||||||
update_new_files.extend(results.new)
|
update_new_files.extend(results.new)
|
||||||
@@ -618,6 +622,7 @@ def export2(
|
|||||||
touch_file,
|
touch_file,
|
||||||
convert_to_jpeg,
|
convert_to_jpeg,
|
||||||
fileutil=fileutil,
|
fileutil=fileutil,
|
||||||
|
jpeg_quality=jpeg_quality,
|
||||||
)
|
)
|
||||||
exported_files.extend(results.exported)
|
exported_files.extend(results.exported)
|
||||||
update_new_files.extend(results.new)
|
update_new_files.extend(results.new)
|
||||||
@@ -823,6 +828,7 @@ def _export_photo(
|
|||||||
convert_to_jpeg,
|
convert_to_jpeg,
|
||||||
fileutil=FileUtil,
|
fileutil=FileUtil,
|
||||||
edited=False,
|
edited=False,
|
||||||
|
jpeg_quality=1.0,
|
||||||
):
|
):
|
||||||
""" Helper function for export()
|
""" Helper function for export()
|
||||||
Does the actual copy or hardlink taking the appropriate
|
Does the actual copy or hardlink taking the appropriate
|
||||||
@@ -842,6 +848,9 @@ def _export_photo(
|
|||||||
touch_file: bool
|
touch_file: bool
|
||||||
convert_to_jpeg: bool; if True, convert file to jpeg on export
|
convert_to_jpeg: bool; if True, convert file to jpeg on export
|
||||||
fileutil: FileUtil class that conforms to fileutil.FileUtilABC
|
fileutil: FileUtil class that conforms to fileutil.FileUtilABC
|
||||||
|
edited: bool; set to True if exporting edited version of photo
|
||||||
|
jpeg_quality: float in range 0.0 <= jpeg_quality <= 1.0. A value of 1.0 specifies use best quality, a value of 0.0 specifies use maximum compression.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
ExportResults
|
ExportResults
|
||||||
|
|
||||||
@@ -949,7 +958,7 @@ def _export_photo(
|
|||||||
fileutil.hardlink(src, dest)
|
fileutil.hardlink(src, dest)
|
||||||
elif convert_to_jpeg:
|
elif convert_to_jpeg:
|
||||||
# use convert_to_jpeg to export the file
|
# use convert_to_jpeg to export the file
|
||||||
fileutil.convert_to_jpeg(src, dest_str)
|
fileutil.convert_to_jpeg(src, dest_str, compression_quality=jpeg_quality)
|
||||||
converted_stat = fileutil.file_sig(dest_str)
|
converted_stat = fileutil.file_sig(dest_str)
|
||||||
else:
|
else:
|
||||||
fileutil.copy(src, dest_str, norsrc=no_xattr)
|
fileutil.copy(src, dest_str, norsrc=no_xattr)
|
||||||
|
|||||||
BIN
tests/test-images/DSC03584.dng
Executable file
BIN
tests/test-images/DSC03584.dng
Executable file
Binary file not shown.
@@ -7,8 +7,8 @@ PHOTOS_DB = "tests/Test-10.16.0.photoslibrary/database/photos.db"
|
|||||||
PHOTOS_DB_PATH = "/Test-10.16.0.photoslibrary/database/photos.db"
|
PHOTOS_DB_PATH = "/Test-10.16.0.photoslibrary/database/photos.db"
|
||||||
PHOTOS_LIBRARY_PATH = "/Test-10.16.0.photoslibrary"
|
PHOTOS_LIBRARY_PATH = "/Test-10.16.0.photoslibrary"
|
||||||
|
|
||||||
PHOTOS_DB_LEN = 15
|
PHOTOS_DB_LEN = 16
|
||||||
PHOTOS_NOT_IN_TRASH_LEN = 13
|
PHOTOS_NOT_IN_TRASH_LEN = 14
|
||||||
PHOTOS_IN_TRASH_LEN = 2
|
PHOTOS_IN_TRASH_LEN = 2
|
||||||
|
|
||||||
KEYWORDS = [
|
KEYWORDS = [
|
||||||
@@ -31,6 +31,8 @@ ALBUMS = [
|
|||||||
"Raw",
|
"Raw",
|
||||||
"I have a deleted twin", # there's an empty album with same name that has been deleted
|
"I have a deleted twin", # there's an empty album with same name that has been deleted
|
||||||
"EmptyAlbum",
|
"EmptyAlbum",
|
||||||
|
"2018-10 - Sponsion, Museum, Frühstück, Römermuseum",
|
||||||
|
"2019-10/11 Paris Clermont",
|
||||||
]
|
]
|
||||||
KEYWORDS_DICT = {
|
KEYWORDS_DICT = {
|
||||||
"Kids": 4,
|
"Kids": 4,
|
||||||
@@ -51,6 +53,8 @@ ALBUM_DICT = {
|
|||||||
"Raw": 4,
|
"Raw": 4,
|
||||||
"I have a deleted twin": 1,
|
"I have a deleted twin": 1,
|
||||||
"EmptyAlbum": 0,
|
"EmptyAlbum": 0,
|
||||||
|
"2018-10 - Sponsion, Museum, Frühstück, Römermuseum": 1,
|
||||||
|
"2019-10/11 Paris Clermont": 1,
|
||||||
} # Note: there are 2 albums named "Test Album" for testing duplicate album names
|
} # Note: there are 2 albums named "Test Album" for testing duplicate album names
|
||||||
|
|
||||||
UUID_DICT = {
|
UUID_DICT = {
|
||||||
@@ -617,9 +621,7 @@ def test_get_db_connection():
|
|||||||
assert isinstance(conn, sqlite3.Connection)
|
assert isinstance(conn, sqlite3.Connection)
|
||||||
assert isinstance(cursor, sqlite3.Cursor)
|
assert isinstance(cursor, sqlite3.Cursor)
|
||||||
|
|
||||||
results = conn.execute(
|
results = conn.execute("SELECT ZUUID FROM ZASSET WHERE ZFAVORITE = 1;").fetchall()
|
||||||
"SELECT ZUUID FROM ZASSET WHERE ZFAVORITE = 1;"
|
|
||||||
).fetchall()
|
|
||||||
assert len(results) == 1
|
assert len(results) == 1
|
||||||
assert results[0][0] == "E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51" # uuid
|
assert results[0][0] == "E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51" # uuid
|
||||||
|
|
||||||
@@ -1032,7 +1034,7 @@ def test_from_to_date():
|
|||||||
photosdb = osxphotos.PhotosDB(PHOTOS_DB)
|
photosdb = osxphotos.PhotosDB(PHOTOS_DB)
|
||||||
|
|
||||||
photos = photosdb.photos(from_date=dt.datetime(2018, 10, 28))
|
photos = photosdb.photos(from_date=dt.datetime(2018, 10, 28))
|
||||||
assert len(photos) == 6
|
assert len(photos) == 7
|
||||||
|
|
||||||
photos = photosdb.photos(to_date=dt.datetime(2018, 10, 28))
|
photos = photosdb.photos(to_date=dt.datetime(2018, 10, 28))
|
||||||
assert len(photos) == 7
|
assert len(photos) == 7
|
||||||
|
|||||||
@@ -93,6 +93,27 @@ CLI_EXPORT_FILENAMES_CURRENT = [
|
|||||||
"F12384F6-CD17-4151-ACBA-AE0E3688539E.jpeg",
|
"F12384F6-CD17-4151-ACBA-AE0E3688539E.jpeg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
CLI_EXPORT_FILENAMES_CONVERT_TO_JPEG = [
|
||||||
|
"DSC03584.jpeg",
|
||||||
|
"IMG_1693.jpeg",
|
||||||
|
"IMG_1994.JPG",
|
||||||
|
"IMG_1994.cr2",
|
||||||
|
"IMG_1997.JPG",
|
||||||
|
"IMG_1997.cr2",
|
||||||
|
"IMG_3092.jpeg",
|
||||||
|
"IMG_4547.jpg",
|
||||||
|
"Pumkins1.jpg",
|
||||||
|
"Pumkins2.jpg",
|
||||||
|
"Pumpkins3.jpg",
|
||||||
|
"St James Park.jpg",
|
||||||
|
"St James Park_edited.jpeg",
|
||||||
|
"Tulips.jpg",
|
||||||
|
"Tulips_edited.jpeg",
|
||||||
|
"wedding.jpg",
|
||||||
|
"wedding_edited.jpeg",
|
||||||
|
]
|
||||||
|
|
||||||
|
CLI_EXPORT_CONVERT_TO_JPEG_LARGE_FILE = "DSC03584.jpeg"
|
||||||
|
|
||||||
CLI_EXPORTED_DIRECTORY_TEMPLATE_FILENAMES1 = [
|
CLI_EXPORTED_DIRECTORY_TEMPLATE_FILENAMES1 = [
|
||||||
"2019/April/wedding.jpg",
|
"2019/April/wedding.jpg",
|
||||||
@@ -819,6 +840,58 @@ def test_export_edited_suffix():
|
|||||||
assert sorted(files) == sorted(CLI_EXPORT_FILENAMES_EDITED_SUFFIX)
|
assert sorted(files) == sorted(CLI_EXPORT_FILENAMES_EDITED_SUFFIX)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_convert_to_jpeg():
|
||||||
|
""" test --convert-to-jpeg """
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import pathlib
|
||||||
|
from osxphotos.__main__ import export
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
cwd = os.getcwd()
|
||||||
|
# pylint: disable=not-context-manager
|
||||||
|
with runner.isolated_filesystem():
|
||||||
|
result = runner.invoke(
|
||||||
|
export, [os.path.join(cwd, PHOTOS_DB_15_6), ".", "-V", "--convert-to-jpeg"]
|
||||||
|
)
|
||||||
|
assert result.exit_code == 0
|
||||||
|
files = glob.glob("*")
|
||||||
|
assert sorted(files) == sorted(CLI_EXPORT_FILENAMES_CONVERT_TO_JPEG)
|
||||||
|
large_file = pathlib.Path(CLI_EXPORT_CONVERT_TO_JPEG_LARGE_FILE)
|
||||||
|
assert large_file.stat().st_size > 10000000
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_convert_to_jpeg_quality():
|
||||||
|
""" test --convert-to-jpeg --jpeg-quality """
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import pathlib
|
||||||
|
from osxphotos.__main__ import export
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
cwd = os.getcwd()
|
||||||
|
# pylint: disable=not-context-manager
|
||||||
|
with runner.isolated_filesystem():
|
||||||
|
result = runner.invoke(
|
||||||
|
export,
|
||||||
|
[
|
||||||
|
os.path.join(cwd, PHOTOS_DB_15_6),
|
||||||
|
".",
|
||||||
|
"-V",
|
||||||
|
"--convert-to-jpeg",
|
||||||
|
"--jpeg-quality",
|
||||||
|
"0.2",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
assert result.exit_code == 0
|
||||||
|
files = glob.glob("*")
|
||||||
|
assert sorted(files) == sorted(CLI_EXPORT_FILENAMES_CONVERT_TO_JPEG)
|
||||||
|
large_file = pathlib.Path(CLI_EXPORT_CONVERT_TO_JPEG_LARGE_FILE)
|
||||||
|
assert large_file.stat().st_size < 1000000
|
||||||
|
|
||||||
|
|
||||||
def test_query_date_1():
|
def test_query_date_1():
|
||||||
""" Test --from-date and --to-date """
|
""" Test --from-date and --to-date """
|
||||||
import json
|
import json
|
||||||
@@ -1826,6 +1899,7 @@ def test_export_filename_template_2():
|
|||||||
files = glob.glob("*.*")
|
files = glob.glob("*.*")
|
||||||
assert sorted(files) == sorted(CLI_EXPORTED_FILENAME_TEMPLATE_FILENAMES2)
|
assert sorted(files) == sorted(CLI_EXPORTED_FILENAME_TEMPLATE_FILENAMES2)
|
||||||
|
|
||||||
|
|
||||||
def test_export_filename_template_pathsep_in_name():
|
def test_export_filename_template_pathsep_in_name():
|
||||||
""" export photos using filename template with folder_album and "/" in album name """
|
""" export photos using filename template with folder_album and "/" in album name """
|
||||||
import locale
|
import locale
|
||||||
@@ -1850,7 +1924,7 @@ def test_export_filename_template_pathsep_in_name():
|
|||||||
"--directory",
|
"--directory",
|
||||||
"{folder_album,None}",
|
"{folder_album,None}",
|
||||||
"--uuid",
|
"--uuid",
|
||||||
CLI_EXPORT_UUID_STATUE
|
CLI_EXPORT_UUID_STATUE,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
@@ -1858,6 +1932,7 @@ def test_export_filename_template_pathsep_in_name():
|
|||||||
# assert fname in result.output
|
# assert fname in result.output
|
||||||
assert pathlib.Path(fname).is_file()
|
assert pathlib.Path(fname).is_file()
|
||||||
|
|
||||||
|
|
||||||
def test_export_filename_template_3():
|
def test_export_filename_template_3():
|
||||||
""" test --filename with invalid template """
|
""" test --filename with invalid template """
|
||||||
import glob
|
import glob
|
||||||
@@ -2632,8 +2707,12 @@ def test_export_update_no_db():
|
|||||||
export, [os.path.join(cwd, CLI_PHOTOS_DB), ".", "--update"]
|
export, [os.path.join(cwd, CLI_PHOTOS_DB), ".", "--update"]
|
||||||
)
|
)
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
|
|
||||||
|
# unedited files will be skipped because their signatures will compare but
|
||||||
|
# edited files will be re-exported because there won't be an edited signature
|
||||||
|
# in the database
|
||||||
assert (
|
assert (
|
||||||
"Exported: 0 photos, updated: 0 photos, skipped: 8 photos, updated EXIF data: 0 photos"
|
"Exported: 0 photos, updated: 2 photos, skipped: 6 photos, updated EXIF data: 0 photos"
|
||||||
in result.output
|
in result.output
|
||||||
)
|
)
|
||||||
assert os.path.isfile(OSXPHOTOS_EXPORT_DB)
|
assert os.path.isfile(OSXPHOTOS_EXPORT_DB)
|
||||||
|
|||||||
@@ -6,18 +6,22 @@ EXIF_DATA = """[{"_CreatedBy": "osxphotos, https://github.com/RhetTbull/osxphoto
|
|||||||
INFO_DATA = """{"uuid": "3DD2C897-F19E-4CA6-8C22-B027D5A71907", "filename": "3DD2C897-F19E-4CA6-8C22-B027D5A71907.jpeg", "original_filename": "IMG_4547.jpg", "date": "2017-06-20T17:18:56.518000+09:30", "description": "\u2068Elder Park\u2069, \u2068Adelaide\u2069, \u2068Australia\u2069", "title": "Elder Park", "keywords": [], "labels": ["Statue", "Art"], "albums": ["AlbumInFolder"], "folders": {"AlbumInFolder": ["Folder1", "SubFolder2"]}, "persons": [], "path": "/Users/rhet/Pictures/Test-10.15.4.photoslibrary/originals/3/3DD2C897-F19E-4CA6-8C22-B027D5A71907.jpeg", "ismissing": false, "hasadjustments": true, "external_edit": false, "favorite": false, "hidden": false, "latitude": -34.91889167000001, "longitude": 138.59686167, "path_edited": "/Users/rhet/Pictures/Test-10.15.4.photoslibrary/resources/renders/3/3DD2C897-F19E-4CA6-8C22-B027D5A71907_1_201_a.jpeg", "shared": false, "isphoto": true, "ismovie": false, "uti": "public.jpeg", "burst": false, "live_photo": false, "path_live_photo": null, "iscloudasset": false, "incloud": null, "date_modified": "2020-05-18T14:42:04.608664+09:30", "portrait": false, "screenshot": false, "slow_mo": false, "time_lapse": false, "hdr": false, "selfie": false, "panorama": false, "has_raw": false, "uti_raw": null, "path_raw": null, "place": {"name": "Elder Park, Adelaide, South Australia, Australia, River Torrens", "names": {"field0": [], "country": ["Australia"], "state_province": ["South Australia"], "sub_administrative_area": ["Adelaide"], "city": ["Adelaide", "Adelaide"], "field5": [], "additional_city_info": ["Adelaide CBD", "Tarndanya"], "ocean": [], "area_of_interest": ["Elder Park", ""], "inland_water": ["River Torrens", "River Torrens"], "field10": [], "region": [], "sub_throughfare": [], "field13": [], "postal_code": [], "field15": [], "field16": [], "street_address": [], "body_of_water": ["River Torrens", "River Torrens"]}, "country_code": "AU", "ishome": false, "address_str": "River Torrens, Adelaide SA, Australia", "address": {"street": null, "sub_locality": "Tarndanya", "city": "Adelaide", "sub_administrative_area": "Adelaide", "state_province": "SA", "postal_code": null, "country": "Australia", "iso_country_code": "AU"}}, "exif": {"flash_fired": false, "iso": 320, "metering_mode": 3, "sample_rate": null, "track_format": null, "white_balance": 0, "aperture": 2.2, "bit_rate": null, "duration": null, "exposure_bias": 0.0, "focal_length": 4.15, "fps": null, "latitude": null, "longitude": null, "shutter_speed": 0.058823529411764705, "camera_make": "Apple", "camera_model": "iPhone 6s", "codec": null, "lens_model": "iPhone 6s back camera 4.15mm f/2.2"}}"""
|
INFO_DATA = """{"uuid": "3DD2C897-F19E-4CA6-8C22-B027D5A71907", "filename": "3DD2C897-F19E-4CA6-8C22-B027D5A71907.jpeg", "original_filename": "IMG_4547.jpg", "date": "2017-06-20T17:18:56.518000+09:30", "description": "\u2068Elder Park\u2069, \u2068Adelaide\u2069, \u2068Australia\u2069", "title": "Elder Park", "keywords": [], "labels": ["Statue", "Art"], "albums": ["AlbumInFolder"], "folders": {"AlbumInFolder": ["Folder1", "SubFolder2"]}, "persons": [], "path": "/Users/rhet/Pictures/Test-10.15.4.photoslibrary/originals/3/3DD2C897-F19E-4CA6-8C22-B027D5A71907.jpeg", "ismissing": false, "hasadjustments": true, "external_edit": false, "favorite": false, "hidden": false, "latitude": -34.91889167000001, "longitude": 138.59686167, "path_edited": "/Users/rhet/Pictures/Test-10.15.4.photoslibrary/resources/renders/3/3DD2C897-F19E-4CA6-8C22-B027D5A71907_1_201_a.jpeg", "shared": false, "isphoto": true, "ismovie": false, "uti": "public.jpeg", "burst": false, "live_photo": false, "path_live_photo": null, "iscloudasset": false, "incloud": null, "date_modified": "2020-05-18T14:42:04.608664+09:30", "portrait": false, "screenshot": false, "slow_mo": false, "time_lapse": false, "hdr": false, "selfie": false, "panorama": false, "has_raw": false, "uti_raw": null, "path_raw": null, "place": {"name": "Elder Park, Adelaide, South Australia, Australia, River Torrens", "names": {"field0": [], "country": ["Australia"], "state_province": ["South Australia"], "sub_administrative_area": ["Adelaide"], "city": ["Adelaide", "Adelaide"], "field5": [], "additional_city_info": ["Adelaide CBD", "Tarndanya"], "ocean": [], "area_of_interest": ["Elder Park", ""], "inland_water": ["River Torrens", "River Torrens"], "field10": [], "region": [], "sub_throughfare": [], "field13": [], "postal_code": [], "field15": [], "field16": [], "street_address": [], "body_of_water": ["River Torrens", "River Torrens"]}, "country_code": "AU", "ishome": false, "address_str": "River Torrens, Adelaide SA, Australia", "address": {"street": null, "sub_locality": "Tarndanya", "city": "Adelaide", "sub_administrative_area": "Adelaide", "state_province": "SA", "postal_code": null, "country": "Australia", "iso_country_code": "AU"}}, "exif": {"flash_fired": false, "iso": 320, "metering_mode": 3, "sample_rate": null, "track_format": null, "white_balance": 0, "aperture": 2.2, "bit_rate": null, "duration": null, "exposure_bias": 0.0, "focal_length": 4.15, "fps": null, "latitude": null, "longitude": null, "shutter_speed": 0.058823529411764705, "camera_make": "Apple", "camera_model": "iPhone 6s", "codec": null, "lens_model": "iPhone 6s back camera 4.15mm f/2.2"}}"""
|
||||||
EXIF_DATA2 = """[{"_CreatedBy": "osxphotos, https://github.com/RhetTbull/osxphotos", "XMP:Title": "St. James's Park", "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"], "XMP:Subject": ["London 2018", "St. James's Park", "England", "United Kingdom", "UK", "London"], "EXIF:GPSLatitude": "51 deg 30' 12.86\" N", "EXIF:GPSLongitude": "0 deg 7' 54.50\" W", "Composite:GPSPosition": "51 deg 30' 12.86\" N, 0 deg 7' 54.50\" W", "EXIF:GPSLatitudeRef": "North", "EXIF:GPSLongitudeRef": "West", "EXIF:DateTimeOriginal": "2018:10:13 09:18:12", "EXIF:OffsetTimeOriginal": "-04:00", "EXIF:ModifyDate": "2019:12:08 14:06:44"}]"""
|
EXIF_DATA2 = """[{"_CreatedBy": "osxphotos, https://github.com/RhetTbull/osxphotos", "XMP:Title": "St. James's Park", "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"], "XMP:Subject": ["London 2018", "St. James's Park", "England", "United Kingdom", "UK", "London"], "EXIF:GPSLatitude": "51 deg 30' 12.86\" N", "EXIF:GPSLongitude": "0 deg 7' 54.50\" W", "Composite:GPSPosition": "51 deg 30' 12.86\" N, 0 deg 7' 54.50\" W", "EXIF:GPSLatitudeRef": "North", "EXIF:GPSLongitudeRef": "West", "EXIF:DateTimeOriginal": "2018:10:13 09:18:12", "EXIF:OffsetTimeOriginal": "-04:00", "EXIF:ModifyDate": "2019:12:08 14:06:44"}]"""
|
||||||
INFO_DATA2 = """{"uuid": "F2BB3F98-90F0-4E4C-A09B-25C6822A4529", "filename": "F2BB3F98-90F0-4E4C-A09B-25C6822A4529.jpeg", "original_filename": "IMG_8440.JPG", "date": "2019-06-11T11:42:06.711805-07:00", "description": null, "title": null, "keywords": [], "labels": ["Sky", "Cloudy", "Fence", "Land", "Outdoor", "Park", "Amusement Park", "Roller Coaster"], "albums": [], "folders": {}, "persons": [], "path": "/Volumes/MacBook Catalina - Data/Users/rhet/Pictures/Photos Library.photoslibrary/originals/F/F2BB3F98-90F0-4E4C-A09B-25C6822A4529.jpeg", "ismissing": false, "hasadjustments": false, "external_edit": false, "favorite": false, "hidden": false, "latitude": 33.81558666666667, "longitude": -117.99298, "path_edited": null, "shared": false, "isphoto": true, "ismovie": false, "uti": "public.jpeg", "burst": false, "live_photo": false, "path_live_photo": null, "iscloudasset": true, "incloud": true, "date_modified": "2019-10-14T00:51:47.141950-07:00", "portrait": false, "screenshot": false, "slow_mo": false, "time_lapse": false, "hdr": false, "selfie": false, "panorama": false, "has_raw": false, "uti_raw": null, "path_raw": null, "place": {"name": "Adventure City, Stanton, California, United States", "names": {"field0": [], "country": ["United States"], "state_province": ["California"], "sub_administrative_area": ["Orange"], "city": ["Stanton", "Anaheim", "Anaheim"], "field5": [], "additional_city_info": ["West Anaheim"], "ocean": [], "area_of_interest": ["Adventure City", "Adventure City"], "inland_water": [], "field10": [], "region": [], "sub_throughfare": [], "field13": [], "postal_code": [], "field15": [], "field16": [], "street_address": [], "body_of_water": []}, "country_code": "US", "ishome": false, "address_str": "Adventure City, 1240 S Beach Blvd, Anaheim, CA 92804, United States", "address": {"street": "1240 S Beach Blvd", "sub_locality": "West Anaheim", "city": "Stanton", "sub_administrative_area": "Orange", "state_province": "CA", "postal_code": "92804", "country": "United States", "iso_country_code": "US"}}, "exif": {"flash_fired": false, "iso": 25, "metering_mode": 5, "sample_rate": null, "track_format": null, "white_balance": 0, "aperture": 2.2, "bit_rate": null, "duration": null, "exposure_bias": 0.0, "focal_length": 4.15, "fps": null, "latitude": null, "longitude": null, "shutter_speed": 0.0004940711462450593, "camera_make": "Apple", "camera_model": "iPhone 6s", "codec": null, "lens_model": "iPhone 6s back camera 4.15mm f/2.2"}}"""
|
INFO_DATA2 = """{"uuid": "F2BB3F98-90F0-4E4C-A09B-25C6822A4529", "filename": "F2BB3F98-90F0-4E4C-A09B-25C6822A4529.jpeg", "original_filename": "IMG_8440.JPG", "date": "2019-06-11T11:42:06.711805-07:00", "description": null, "title": null, "keywords": [], "labels": ["Sky", "Cloudy", "Fence", "Land", "Outdoor", "Park", "Amusement Park", "Roller Coaster"], "albums": [], "folders": {}, "persons": [], "path": "/Volumes/MacBook Catalina - Data/Users/rhet/Pictures/Photos Library.photoslibrary/originals/F/F2BB3F98-90F0-4E4C-A09B-25C6822A4529.jpeg", "ismissing": false, "hasadjustments": false, "external_edit": false, "favorite": false, "hidden": false, "latitude": 33.81558666666667, "longitude": -117.99298, "path_edited": null, "shared": false, "isphoto": true, "ismovie": false, "uti": "public.jpeg", "burst": false, "live_photo": false, "path_live_photo": null, "iscloudasset": true, "incloud": true, "date_modified": "2019-10-14T00:51:47.141950-07:00", "portrait": false, "screenshot": false, "slow_mo": false, "time_lapse": false, "hdr": false, "selfie": false, "panorama": false, "has_raw": false, "uti_raw": null, "path_raw": null, "place": {"name": "Adventure City, Stanton, California, United States", "names": {"field0": [], "country": ["United States"], "state_province": ["California"], "sub_administrative_area": ["Orange"], "city": ["Stanton", "Anaheim", "Anaheim"], "field5": [], "additional_city_info": ["West Anaheim"], "ocean": [], "area_of_interest": ["Adventure City", "Adventure City"], "inland_water": [], "field10": [], "region": [], "sub_throughfare": [], "field13": [], "postal_code": [], "field15": [], "field16": [], "street_address": [], "body_of_water": []}, "country_code": "US", "ishome": false, "address_str": "Adventure City, 1240 S Beach Blvd, Anaheim, CA 92804, United States", "address": {"street": "1240 S Beach Blvd", "sub_locality": "West Anaheim", "city": "Stanton", "sub_administrative_area": "Orange", "state_province": "CA", "postal_code": "92804", "country": "United States", "iso_country_code": "US"}}, "exif": {"flash_fired": false, "iso": 25, "metering_mode": 5, "sample_rate": null, "track_format": null, "white_balance": 0, "aperture": 2.2, "bit_rate": null, "duration": null, "exposure_bias": 0.0, "focal_length": 4.15, "fps": null, "latitude": null, "longitude": null, "shutter_speed": 0.0004940711462450593, "camera_make": "Apple", "camera_model": "iPhone 6s", "codec": null, "lens_model": "iPhone 6s back camera 4.15mm f/2.2"}}"""
|
||||||
|
DATABASE_VERSION1 = "tests/export_db_version1.db"
|
||||||
|
|
||||||
|
|
||||||
def test_export_db():
|
def test_export_db():
|
||||||
""" test ExportDB """
|
""" test ExportDB """
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
from osxphotos.export_db import ExportDB
|
from osxphotos.export_db import ExportDB, OSXPHOTOS_EXPORTDB_VERSION
|
||||||
|
|
||||||
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
||||||
dbname = os.path.join(tempdir.name, ".osxphotos_export.db")
|
dbname = os.path.join(tempdir.name, ".osxphotos_export.db")
|
||||||
db = ExportDB(dbname)
|
db = ExportDB(dbname)
|
||||||
assert os.path.isfile(dbname)
|
assert os.path.isfile(dbname)
|
||||||
|
assert db.was_created
|
||||||
|
assert not db.was_upgraded
|
||||||
|
assert db.version == OSXPHOTOS_EXPORTDB_VERSION
|
||||||
|
|
||||||
filepath = os.path.join(tempdir.name, "test.JPG")
|
filepath = os.path.join(tempdir.name, "test.JPG")
|
||||||
filepath_lower = os.path.join(tempdir.name, "test.jpg")
|
filepath_lower = os.path.join(tempdir.name, "test.jpg")
|
||||||
@@ -33,24 +37,42 @@ def test_export_db():
|
|||||||
assert db.get_stat_orig_for_file(filepath) == (1, 2, 3)
|
assert db.get_stat_orig_for_file(filepath) == (1, 2, 3)
|
||||||
db.set_stat_exif_for_file(filepath, (4, 5, 6))
|
db.set_stat_exif_for_file(filepath, (4, 5, 6))
|
||||||
assert db.get_stat_exif_for_file(filepath) == (4, 5, 6)
|
assert db.get_stat_exif_for_file(filepath) == (4, 5, 6)
|
||||||
|
db.set_stat_edited_for_file(filepath, (10, 11, 12))
|
||||||
|
assert db.get_stat_edited_for_file(filepath) == (10, 11, 12)
|
||||||
|
db.set_stat_converted_for_file(filepath, (7, 8, 9))
|
||||||
|
assert db.get_stat_converted_for_file(filepath) == (7, 8, 9)
|
||||||
|
|
||||||
# test set_data which sets all at the same time
|
# test set_data which sets all at the same time
|
||||||
filepath2 = os.path.join(tempdir.name, "test2.jpg")
|
filepath2 = os.path.join(tempdir.name, "test2.jpg")
|
||||||
db.set_data(filepath2, "BAR-FOO", (1, 2, 3), (4, 5, 6), INFO_DATA, EXIF_DATA)
|
db.set_data(
|
||||||
|
filepath2,
|
||||||
|
"BAR-FOO",
|
||||||
|
(1, 2, 3),
|
||||||
|
(4, 5, 6),
|
||||||
|
(7, 8, 9),
|
||||||
|
(10, 11, 12),
|
||||||
|
INFO_DATA,
|
||||||
|
EXIF_DATA,
|
||||||
|
)
|
||||||
assert db.get_uuid_for_file(filepath2) == "BAR-FOO"
|
assert db.get_uuid_for_file(filepath2) == "BAR-FOO"
|
||||||
assert db.get_info_for_uuid("BAR-FOO") == INFO_DATA
|
assert db.get_info_for_uuid("BAR-FOO") == INFO_DATA
|
||||||
assert db.get_exifdata_for_file(filepath2) == EXIF_DATA
|
assert db.get_exifdata_for_file(filepath2) == EXIF_DATA
|
||||||
assert db.get_stat_orig_for_file(filepath2) == (1, 2, 3)
|
assert db.get_stat_orig_for_file(filepath2) == (1, 2, 3)
|
||||||
assert db.get_stat_exif_for_file(filepath2) == (4, 5, 6)
|
assert db.get_stat_exif_for_file(filepath2) == (4, 5, 6)
|
||||||
|
assert db.get_stat_converted_for_file(filepath2) == (7, 8, 9)
|
||||||
|
assert db.get_stat_edited_for_file(filepath2) == (10, 11, 12)
|
||||||
|
|
||||||
# close and re-open
|
# close and re-open
|
||||||
db.close()
|
db.close()
|
||||||
db = ExportDB(dbname)
|
db = ExportDB(dbname)
|
||||||
|
assert not db.was_created
|
||||||
assert db.get_uuid_for_file(filepath2) == "BAR-FOO"
|
assert db.get_uuid_for_file(filepath2) == "BAR-FOO"
|
||||||
assert db.get_info_for_uuid("BAR-FOO") == INFO_DATA
|
assert db.get_info_for_uuid("BAR-FOO") == INFO_DATA
|
||||||
assert db.get_exifdata_for_file(filepath2) == EXIF_DATA
|
assert db.get_exifdata_for_file(filepath2) == EXIF_DATA
|
||||||
assert db.get_stat_orig_for_file(filepath2) == (1, 2, 3)
|
assert db.get_stat_orig_for_file(filepath2) == (1, 2, 3)
|
||||||
assert db.get_stat_exif_for_file(filepath2) == (4, 5, 6)
|
assert db.get_stat_exif_for_file(filepath2) == (4, 5, 6)
|
||||||
|
assert db.get_stat_converted_for_file(filepath2) == (7, 8, 9)
|
||||||
|
assert db.get_stat_edited_for_file(filepath2) == (10, 11, 12)
|
||||||
|
|
||||||
# update data
|
# update data
|
||||||
db.set_uuid_for_file(filepath, "FUBAR")
|
db.set_uuid_for_file(filepath, "FUBAR")
|
||||||
@@ -61,10 +83,13 @@ def test_export_db_no_op():
|
|||||||
""" test ExportDBNoOp """
|
""" test ExportDBNoOp """
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
from osxphotos._export_db import ExportDBNoOp
|
from osxphotos.export_db import ExportDBNoOp, OSXPHOTOS_EXPORTDB_VERSION
|
||||||
|
|
||||||
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
||||||
db = ExportDBNoOp()
|
db = ExportDBNoOp()
|
||||||
|
assert db.was_created
|
||||||
|
assert not db.was_upgraded
|
||||||
|
assert db.version == OSXPHOTOS_EXPORTDB_VERSION
|
||||||
|
|
||||||
filepath = os.path.join(tempdir.name, "test.JPG")
|
filepath = os.path.join(tempdir.name, "test.JPG")
|
||||||
filepath_lower = os.path.join(tempdir.name, "test.jpg")
|
filepath_lower = os.path.join(tempdir.name, "test.jpg")
|
||||||
@@ -80,15 +105,30 @@ def test_export_db_no_op():
|
|||||||
assert db.get_stat_orig_for_file(filepath) is None
|
assert db.get_stat_orig_for_file(filepath) is None
|
||||||
db.set_stat_exif_for_file(filepath, (4, 5, 6))
|
db.set_stat_exif_for_file(filepath, (4, 5, 6))
|
||||||
assert db.get_stat_exif_for_file(filepath) is None
|
assert db.get_stat_exif_for_file(filepath) is None
|
||||||
|
db.set_stat_converted_for_file(filepath, (7, 8, 9))
|
||||||
|
assert db.get_stat_converted_for_file(filepath) is None
|
||||||
|
db.set_stat_edited_for_file(filepath, (10, 11, 12))
|
||||||
|
assert db.get_stat_edited_for_file(filepath) is None
|
||||||
|
|
||||||
# test set_data which sets all at the same time
|
# test set_data which sets all at the same time
|
||||||
filepath2 = os.path.join(tempdir.name, "test2.jpg")
|
filepath2 = os.path.join(tempdir.name, "test2.jpg")
|
||||||
db.set_data(filepath2, "BAR-FOO", (1, 2, 3), (4, 5, 6), INFO_DATA, EXIF_DATA)
|
db.set_data(
|
||||||
|
filepath2,
|
||||||
|
"BAR-FOO",
|
||||||
|
(1, 2, 3),
|
||||||
|
(4, 5, 6),
|
||||||
|
(7, 8, 9),
|
||||||
|
(10, 11, 12),
|
||||||
|
INFO_DATA,
|
||||||
|
EXIF_DATA,
|
||||||
|
)
|
||||||
assert db.get_uuid_for_file(filepath2) is None
|
assert db.get_uuid_for_file(filepath2) is None
|
||||||
assert db.get_info_for_uuid("BAR-FOO") is None
|
assert db.get_info_for_uuid("BAR-FOO") is None
|
||||||
assert db.get_exifdata_for_file(filepath2) is None
|
assert db.get_exifdata_for_file(filepath2) is None
|
||||||
assert db.get_stat_orig_for_file(filepath2) is None
|
assert db.get_stat_orig_for_file(filepath2) is None
|
||||||
assert db.get_stat_exif_for_file(filepath2) is None
|
assert db.get_stat_exif_for_file(filepath2) is None
|
||||||
|
assert db.get_stat_converted_for_file(filepath) is None
|
||||||
|
assert db.get_stat_edited_for_file(filepath) is None
|
||||||
|
|
||||||
# update data
|
# update data
|
||||||
db.set_uuid_for_file(filepath, "FUBAR")
|
db.set_uuid_for_file(filepath, "FUBAR")
|
||||||
@@ -99,7 +139,11 @@ def test_export_db_in_memory():
|
|||||||
""" test ExportDBInMemory """
|
""" test ExportDBInMemory """
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
from osxphotos._export_db import ExportDB, ExportDBInMemory
|
from osxphotos.export_db import (
|
||||||
|
ExportDB,
|
||||||
|
ExportDBInMemory,
|
||||||
|
OSXPHOTOS_EXPORTDB_VERSION,
|
||||||
|
)
|
||||||
|
|
||||||
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
||||||
dbname = os.path.join(tempdir.name, ".osxphotos_export.db")
|
dbname = os.path.join(tempdir.name, ".osxphotos_export.db")
|
||||||
@@ -114,10 +158,15 @@ def test_export_db_in_memory():
|
|||||||
db.set_exifdata_for_file(filepath, EXIF_DATA)
|
db.set_exifdata_for_file(filepath, EXIF_DATA)
|
||||||
db.set_stat_orig_for_file(filepath, (1, 2, 3))
|
db.set_stat_orig_for_file(filepath, (1, 2, 3))
|
||||||
db.set_stat_exif_for_file(filepath, (4, 5, 6))
|
db.set_stat_exif_for_file(filepath, (4, 5, 6))
|
||||||
|
db.set_stat_converted_for_file(filepath, (7, 8, 9))
|
||||||
|
db.set_stat_edited_for_file(filepath, (10, 11, 12))
|
||||||
|
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
dbram = ExportDBInMemory(dbname)
|
dbram = ExportDBInMemory(dbname)
|
||||||
|
assert not dbram.was_created
|
||||||
|
assert not dbram.was_upgraded
|
||||||
|
assert dbram.version == OSXPHOTOS_EXPORTDB_VERSION
|
||||||
|
|
||||||
# verify values as expected
|
# verify values as expected
|
||||||
assert dbram.get_uuid_for_file(filepath_lower) == "FOO-BAR"
|
assert dbram.get_uuid_for_file(filepath_lower) == "FOO-BAR"
|
||||||
@@ -125,6 +174,8 @@ def test_export_db_in_memory():
|
|||||||
assert dbram.get_exifdata_for_file(filepath) == EXIF_DATA
|
assert dbram.get_exifdata_for_file(filepath) == EXIF_DATA
|
||||||
assert dbram.get_stat_orig_for_file(filepath) == (1, 2, 3)
|
assert dbram.get_stat_orig_for_file(filepath) == (1, 2, 3)
|
||||||
assert dbram.get_stat_exif_for_file(filepath) == (4, 5, 6)
|
assert dbram.get_stat_exif_for_file(filepath) == (4, 5, 6)
|
||||||
|
assert dbram.get_stat_converted_for_file(filepath) == (7, 8, 9)
|
||||||
|
assert dbram.get_stat_edited_for_file(filepath) == (10, 11, 12)
|
||||||
|
|
||||||
# change a value
|
# change a value
|
||||||
dbram.set_uuid_for_file(filepath, "FUBAR")
|
dbram.set_uuid_for_file(filepath, "FUBAR")
|
||||||
@@ -132,12 +183,16 @@ def test_export_db_in_memory():
|
|||||||
dbram.set_exifdata_for_file(filepath, EXIF_DATA2)
|
dbram.set_exifdata_for_file(filepath, EXIF_DATA2)
|
||||||
dbram.set_stat_orig_for_file(filepath, (7, 8, 9))
|
dbram.set_stat_orig_for_file(filepath, (7, 8, 9))
|
||||||
dbram.set_stat_exif_for_file(filepath, (10, 11, 12))
|
dbram.set_stat_exif_for_file(filepath, (10, 11, 12))
|
||||||
|
dbram.set_stat_converted_for_file(filepath, (1, 2, 3))
|
||||||
|
dbram.set_stat_edited_for_file(filepath, (4, 5, 6))
|
||||||
|
|
||||||
assert dbram.get_uuid_for_file(filepath_lower) == "FUBAR"
|
assert dbram.get_uuid_for_file(filepath_lower) == "FUBAR"
|
||||||
assert dbram.get_info_for_uuid("FUBAR") == INFO_DATA2
|
assert dbram.get_info_for_uuid("FUBAR") == INFO_DATA2
|
||||||
assert dbram.get_exifdata_for_file(filepath) == EXIF_DATA2
|
assert dbram.get_exifdata_for_file(filepath) == EXIF_DATA2
|
||||||
assert dbram.get_stat_orig_for_file(filepath) == (7, 8, 9)
|
assert dbram.get_stat_orig_for_file(filepath) == (7, 8, 9)
|
||||||
assert dbram.get_stat_exif_for_file(filepath) == (10, 11, 12)
|
assert dbram.get_stat_exif_for_file(filepath) == (10, 11, 12)
|
||||||
|
assert dbram.get_stat_converted_for_file(filepath) == (1, 2, 3)
|
||||||
|
assert dbram.get_stat_edited_for_file(filepath) == (4, 5, 6)
|
||||||
|
|
||||||
dbram.close()
|
dbram.close()
|
||||||
|
|
||||||
@@ -148,5 +203,42 @@ def test_export_db_in_memory():
|
|||||||
assert db.get_exifdata_for_file(filepath) == EXIF_DATA
|
assert db.get_exifdata_for_file(filepath) == EXIF_DATA
|
||||||
assert db.get_stat_orig_for_file(filepath) == (1, 2, 3)
|
assert db.get_stat_orig_for_file(filepath) == (1, 2, 3)
|
||||||
assert db.get_stat_exif_for_file(filepath) == (4, 5, 6)
|
assert db.get_stat_exif_for_file(filepath) == (4, 5, 6)
|
||||||
|
assert db.get_stat_converted_for_file(filepath) == (7, 8, 9)
|
||||||
|
assert db.get_stat_edited_for_file(filepath) == (10, 11, 12)
|
||||||
|
|
||||||
assert db.get_info_for_uuid("FUBAR") is None
|
assert db.get_info_for_uuid("FUBAR") is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_db_in_memory_nofile():
|
||||||
|
""" test ExportDBInMemory with no dbfile """
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
from osxphotos.export_db import ExportDBInMemory, OSXPHOTOS_EXPORTDB_VERSION
|
||||||
|
|
||||||
|
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
||||||
|
filepath = os.path.join(tempdir.name, "test.JPG")
|
||||||
|
filepath_lower = os.path.join(tempdir.name, "test.jpg")
|
||||||
|
|
||||||
|
dbram = ExportDBInMemory(os.path.join(tempdir.name, "NOT_A_DATABASE_FILE.db"))
|
||||||
|
assert dbram.was_created
|
||||||
|
assert not dbram.was_upgraded
|
||||||
|
assert dbram.version == OSXPHOTOS_EXPORTDB_VERSION
|
||||||
|
|
||||||
|
# change a value
|
||||||
|
dbram.set_uuid_for_file(filepath, "FUBAR")
|
||||||
|
dbram.set_info_for_uuid("FUBAR", INFO_DATA2)
|
||||||
|
dbram.set_exifdata_for_file(filepath, EXIF_DATA2)
|
||||||
|
dbram.set_stat_orig_for_file(filepath, (7, 8, 9))
|
||||||
|
dbram.set_stat_exif_for_file(filepath, (10, 11, 12))
|
||||||
|
dbram.set_stat_converted_for_file(filepath, (1, 2, 3))
|
||||||
|
dbram.set_stat_edited_for_file(filepath, (4, 5, 6))
|
||||||
|
|
||||||
|
assert dbram.get_uuid_for_file(filepath_lower) == "FUBAR"
|
||||||
|
assert dbram.get_info_for_uuid("FUBAR") == INFO_DATA2
|
||||||
|
assert dbram.get_exifdata_for_file(filepath) == EXIF_DATA2
|
||||||
|
assert dbram.get_stat_orig_for_file(filepath) == (7, 8, 9)
|
||||||
|
assert dbram.get_stat_exif_for_file(filepath) == (10, 11, 12)
|
||||||
|
assert dbram.get_stat_converted_for_file(filepath) == (1, 2, 3)
|
||||||
|
assert dbram.get_stat_edited_for_file(filepath) == (4, 5, 6)
|
||||||
|
|
||||||
|
dbram.close()
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
TEST_HEIC = "tests/test-images/IMG_3092.heic"
|
TEST_HEIC = "tests/test-images/IMG_3092.heic"
|
||||||
|
TEST_RAW = "tests/test-images/DSC03584.dng"
|
||||||
|
|
||||||
|
|
||||||
def test_copy_file_valid():
|
def test_copy_file_valid():
|
||||||
# copy file with valid src, dest
|
# copy file with valid src, dest
|
||||||
@@ -23,8 +25,8 @@ def test_copy_file_invalid():
|
|||||||
from osxphotos.fileutil import FileUtil
|
from osxphotos.fileutil import FileUtil
|
||||||
|
|
||||||
temp_dir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
temp_dir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
||||||
src = "tests/test-images/wedding_DOES_NOT_EXIST.jpg"
|
|
||||||
with pytest.raises(Exception) as e:
|
with pytest.raises(Exception) as e:
|
||||||
|
src = "tests/test-images/wedding_DOES_NOT_EXIST.jpg"
|
||||||
assert FileUtil.copy(src, temp_dir.name)
|
assert FileUtil.copy(src, temp_dir.name)
|
||||||
assert e.type == FileNotFoundError
|
assert e.type == FileNotFoundError
|
||||||
|
|
||||||
@@ -69,7 +71,9 @@ def test_unlink_file():
|
|||||||
FileUtil.unlink(dest)
|
FileUtil.unlink(dest)
|
||||||
assert not os.path.isfile(dest)
|
assert not os.path.isfile(dest)
|
||||||
|
|
||||||
|
|
||||||
def test_convert_to_jpeg():
|
def test_convert_to_jpeg():
|
||||||
|
""" test convert_to_jpeg """
|
||||||
import pathlib
|
import pathlib
|
||||||
import tempfile
|
import tempfile
|
||||||
from osxphotos.fileutil import FileUtil
|
from osxphotos.fileutil import FileUtil
|
||||||
@@ -80,3 +84,18 @@ def test_convert_to_jpeg():
|
|||||||
outfile = pathlib.Path(temp_dir.name) / f"{imgfile.stem}.jpeg"
|
outfile = pathlib.Path(temp_dir.name) / f"{imgfile.stem}.jpeg"
|
||||||
assert FileUtil.convert_to_jpeg(imgfile, outfile)
|
assert FileUtil.convert_to_jpeg(imgfile, outfile)
|
||||||
assert outfile.is_file()
|
assert outfile.is_file()
|
||||||
|
|
||||||
|
|
||||||
|
def test_convert_to_jpeg_quality():
|
||||||
|
""" test convert_to_jpeg with compression_quality """
|
||||||
|
import pathlib
|
||||||
|
import tempfile
|
||||||
|
from osxphotos.fileutil import FileUtil
|
||||||
|
|
||||||
|
temp_dir = tempfile.TemporaryDirectory(prefix="osxphotos_")
|
||||||
|
with temp_dir:
|
||||||
|
imgfile = pathlib.Path(TEST_RAW)
|
||||||
|
outfile = pathlib.Path(temp_dir.name) / f"{imgfile.stem}.jpeg"
|
||||||
|
assert FileUtil.convert_to_jpeg(imgfile, outfile, compression_quality=0.1)
|
||||||
|
assert outfile.is_file()
|
||||||
|
assert outfile.stat().st_size < 1000000
|
||||||
|
|||||||
@@ -55,8 +55,9 @@ def test_image_converter_compression_quality():
|
|||||||
outfile = pathlib.Path(tempdir.name) / f"{imgfile.stem}.jpeg"
|
outfile = pathlib.Path(tempdir.name) / f"{imgfile.stem}.jpeg"
|
||||||
|
|
||||||
# call write_jpeg with both pathlib.Path and str arguments
|
# call write_jpeg with both pathlib.Path and str arguments
|
||||||
assert converter.write_jpeg(imgfile, outfile, compression_quality=0.5)
|
assert converter.write_jpeg(imgfile, outfile, compression_quality=0.1)
|
||||||
assert outfile.is_file()
|
assert outfile.is_file()
|
||||||
|
assert outfile.stat().st_size < 1000000
|
||||||
|
|
||||||
|
|
||||||
def test_image_converter_bad_compression_quality():
|
def test_image_converter_bad_compression_quality():
|
||||||
|
|||||||
Reference in New Issue
Block a user