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) "
|
||||
"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(
|
||||
"--sidecar",
|
||||
default=None,
|
||||
@@ -1356,6 +1365,7 @@ def export(
|
||||
description_template,
|
||||
current_name,
|
||||
convert_to_jpeg,
|
||||
jpeg_quality,
|
||||
sidecar,
|
||||
only_photos,
|
||||
only_movies,
|
||||
@@ -1628,6 +1638,7 @@ def export(
|
||||
edited_suffix=edited_suffix,
|
||||
use_photos_export=use_photos_export,
|
||||
convert_to_jpeg=convert_to_jpeg,
|
||||
jpeg_quality=jpeg_quality,
|
||||
)
|
||||
results_exported.extend(results.exported)
|
||||
results_new.extend(results.new)
|
||||
@@ -1676,6 +1687,7 @@ def export(
|
||||
edited_suffix=edited_suffix,
|
||||
use_photos_export=use_photos_export,
|
||||
convert_to_jpeg=convert_to_jpeg,
|
||||
jpeg_quality=jpeg_quality,
|
||||
)
|
||||
results_exported.extend(results.exported)
|
||||
results_new.extend(results.new)
|
||||
@@ -2167,6 +2179,7 @@ def export_photo(
|
||||
edited_suffix="_edited",
|
||||
use_photos_export=False,
|
||||
convert_to_jpeg=False,
|
||||
jpeg_quality=1.0,
|
||||
):
|
||||
""" 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
|
||||
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
|
||||
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:
|
||||
list of path(s) of exported photo or None if photo was missing
|
||||
@@ -2286,6 +2300,7 @@ def export_photo(
|
||||
dry_run=dry_run,
|
||||
touch_file=touch_file,
|
||||
convert_to_jpeg=convert_to_jpeg,
|
||||
jpeg_quality=jpeg_quality,
|
||||
)
|
||||
|
||||
results_exported.extend(export_results.exported)
|
||||
@@ -2346,6 +2361,7 @@ def export_photo(
|
||||
dry_run=dry_run,
|
||||
touch_file=touch_file,
|
||||
convert_to_jpeg=convert_to_jpeg,
|
||||
jpeg_quality=jpeg_quality,
|
||||
)
|
||||
|
||||
results_exported.extend(export_results_edited.exported)
|
||||
|
||||
@@ -94,6 +94,11 @@ class ExportDB_ABC(ABC):
|
||||
class ExportDBNoOp(ExportDB_ABC):
|
||||
""" 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):
|
||||
pass
|
||||
|
||||
@@ -441,36 +446,27 @@ class ExportDB(ExportDB_ABC):
|
||||
raise ValueError(f"expected 3 elements for stat, got {len(stats)}")
|
||||
|
||||
conn = self._conn
|
||||
try:
|
||||
c = conn.cursor()
|
||||
c.execute(
|
||||
f"UPDATE {table} "
|
||||
+ "SET converted_mode = ?, converted_size = ?, converted_mtime = ? "
|
||||
+ "WHERE filepath_normalized = ?;",
|
||||
(*stats, filename),
|
||||
)
|
||||
conn.commit()
|
||||
except Error as e:
|
||||
logging.warning(e)
|
||||
c = conn.cursor()
|
||||
c.execute(
|
||||
f"INSERT OR REPLACE INTO {table}(filepath_normalized, mode, size, mtime) VALUES (?, ?, ?, ?);",
|
||||
(filename, *stats),
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
def _get_stat_for_file(self, table, filename):
|
||||
filename = str(pathlib.Path(filename).relative_to(self._path)).lower()
|
||||
conn = self._conn
|
||||
try:
|
||||
c = conn.cursor()
|
||||
c.execute(
|
||||
f"SELECT mode, size, mtime FROM {table} WHERE filepath_normalized = ?",
|
||||
(filename,),
|
||||
)
|
||||
results = c.fetchone()
|
||||
if results:
|
||||
stats = results[0:3]
|
||||
mtime = int(stats[2]) if stats[2] is not None else None
|
||||
stats = (stats[0], stats[1], mtime)
|
||||
else:
|
||||
stats = (None, None, None)
|
||||
except Error as e:
|
||||
logging.warning(e)
|
||||
c = conn.cursor()
|
||||
c.execute(
|
||||
f"SELECT mode, size, mtime FROM {table} WHERE filepath_normalized = ?",
|
||||
(filename,),
|
||||
)
|
||||
results = c.fetchone()
|
||||
if results:
|
||||
stats = results[0:3]
|
||||
mtime = int(stats[2]) if stats[2] is not None else None
|
||||
stats = (stats[0], stats[1], mtime)
|
||||
else:
|
||||
stats = (None, None, None)
|
||||
|
||||
return stats
|
||||
@@ -636,7 +632,6 @@ class ExportDBInMemory(ExportDB):
|
||||
|
||||
def _open_export_db(self, dbfile):
|
||||
""" open export database and return a db connection
|
||||
if dbfile does not exist, will create and initialize the database
|
||||
returns: connection to the database
|
||||
"""
|
||||
if not os.path.isfile(dbfile):
|
||||
|
||||
@@ -177,7 +177,7 @@ class FileUtilMacOS(FileUtilABC):
|
||||
Args:
|
||||
src_file: image file to convert
|
||||
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:
|
||||
True if success, otherwise False
|
||||
|
||||
@@ -307,6 +307,7 @@ def export2(
|
||||
dry_run=False,
|
||||
touch_file=False,
|
||||
convert_to_jpeg=False,
|
||||
jpeg_quality=1.0,
|
||||
):
|
||||
""" export photo, like export but with update and dry_run options
|
||||
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
|
||||
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
|
||||
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
|
||||
where each field is a list of file paths
|
||||
@@ -562,6 +564,7 @@ def export2(
|
||||
convert_to_jpeg,
|
||||
fileutil=fileutil,
|
||||
edited=edited,
|
||||
jpeg_quality=jpeg_quality,
|
||||
)
|
||||
exported_files = results.exported
|
||||
update_new_files = results.new
|
||||
@@ -590,6 +593,7 @@ def export2(
|
||||
touch_file,
|
||||
convert_to_jpeg,
|
||||
fileutil=fileutil,
|
||||
jpeg_quality=jpeg_quality,
|
||||
)
|
||||
exported_files.extend(results.exported)
|
||||
update_new_files.extend(results.new)
|
||||
@@ -618,6 +622,7 @@ def export2(
|
||||
touch_file,
|
||||
convert_to_jpeg,
|
||||
fileutil=fileutil,
|
||||
jpeg_quality=jpeg_quality,
|
||||
)
|
||||
exported_files.extend(results.exported)
|
||||
update_new_files.extend(results.new)
|
||||
@@ -823,6 +828,7 @@ def _export_photo(
|
||||
convert_to_jpeg,
|
||||
fileutil=FileUtil,
|
||||
edited=False,
|
||||
jpeg_quality=1.0,
|
||||
):
|
||||
""" Helper function for export()
|
||||
Does the actual copy or hardlink taking the appropriate
|
||||
@@ -842,6 +848,9 @@ def _export_photo(
|
||||
touch_file: bool
|
||||
convert_to_jpeg: bool; if True, convert file to jpeg on export
|
||||
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:
|
||||
ExportResults
|
||||
|
||||
@@ -949,7 +958,7 @@ def _export_photo(
|
||||
fileutil.hardlink(src, dest)
|
||||
elif convert_to_jpeg:
|
||||
# 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)
|
||||
else:
|
||||
fileutil.copy(src, dest_str, norsrc=no_xattr)
|
||||
|
||||
Reference in New Issue
Block a user