Added --debug and crash reporter to export, #628
This commit is contained in:
@@ -61,6 +61,7 @@ from .configoptions import (
|
||||
ConfigOptionsInvalidError,
|
||||
ConfigOptionsLoadError,
|
||||
)
|
||||
from .crash_reporter import crash_reporter
|
||||
from .datetime_formatter import DateTimeFormatter
|
||||
from .exiftool import get_exiftool_path
|
||||
from .export_db import ExportDB, ExportDBInMemory
|
||||
@@ -135,12 +136,19 @@ __all__ = [
|
||||
VERBOSE = False
|
||||
VERBOSE_TIMESTAMP = False
|
||||
|
||||
# global variable to control debug output
|
||||
# set via --debug
|
||||
DEBUG = False
|
||||
|
||||
# used to show/hide hidden commands
|
||||
OSXPHOTOS_HIDDEN = not bool(os.getenv("OSXPHOTOS_SHOW_HIDDEN", default=False))
|
||||
|
||||
# used by snap and diff commands
|
||||
OSXPHOTOS_SNAPSHOT_DIR = "/private/tmp/osxphotos_snapshots"
|
||||
|
||||
# where to write the crash report if osxphotos crashes
|
||||
OSXPHOTOS_CRASH_LOG = os.getcwd() + "/osxphotos_crash.log"
|
||||
|
||||
rich.traceback.install()
|
||||
|
||||
|
||||
@@ -674,7 +682,7 @@ def QUERY_OPTIONS(f):
|
||||
@click.version_option(__version__, "--version", "-v")
|
||||
@click.pass_context
|
||||
def cli(ctx, db, json_, debug):
|
||||
ctx.obj = CLI_Obj(db=db, json=json_, debug=debug)
|
||||
ctx.obj = CLI_Obj(db=db, json=json_)
|
||||
|
||||
|
||||
@cli.command(cls=ExportCommand)
|
||||
@@ -1205,10 +1213,25 @@ def cli(ctx, db, json_, debug):
|
||||
f"Can be specified multiple times. Valid options are: {PROFILE_SORT_KEYS}. "
|
||||
"Default = 'cumulative'.",
|
||||
)
|
||||
@click.option(
|
||||
"--debug",
|
||||
required=False,
|
||||
is_flag=True,
|
||||
default=False,
|
||||
hidden=OSXPHOTOS_HIDDEN,
|
||||
help="Enable debug output.",
|
||||
)
|
||||
@DB_ARGUMENT
|
||||
@click.argument("dest", nargs=1, type=click.Path(exists=True))
|
||||
@click.pass_obj
|
||||
@click.pass_context
|
||||
@crash_reporter(
|
||||
OSXPHOTOS_CRASH_LOG,
|
||||
"[red]Something went wrong and osxphotos encountered an error:[/red]",
|
||||
"osxphotos crash log",
|
||||
"Please file a bug report at https://github.com/RhetTbull/osxphotos/issues with the crash log attached.",
|
||||
f"osxphotos version: {__version__}",
|
||||
)
|
||||
def export(
|
||||
ctx,
|
||||
cli_obj,
|
||||
@@ -1347,6 +1370,7 @@ def export(
|
||||
preview_if_missing,
|
||||
profile,
|
||||
profile_sort,
|
||||
debug,
|
||||
):
|
||||
"""Export photos from the Photos database.
|
||||
Export path DEST is required.
|
||||
@@ -1360,6 +1384,11 @@ def export(
|
||||
to modify this behavior.
|
||||
"""
|
||||
|
||||
global DEBUG
|
||||
if debug:
|
||||
DEBUG = True
|
||||
osxphotos._set_debug(True)
|
||||
|
||||
if profile:
|
||||
click.echo("Profiling...")
|
||||
profile_sort = profile_sort or ["cumulative"]
|
||||
@@ -1403,7 +1432,7 @@ def export(
|
||||
),
|
||||
err=True,
|
||||
)
|
||||
raise click.Abort()
|
||||
sys.exit(1)
|
||||
|
||||
# re-set the local vars to the corresponding config value
|
||||
# this isn't elegant but avoids having to rewrite this function to use cfg.varname for every parameter
|
||||
@@ -1589,7 +1618,7 @@ def export(
|
||||
),
|
||||
err=True,
|
||||
)
|
||||
raise click.Abort()
|
||||
sys.exit(1)
|
||||
|
||||
if all(x in [s.lower() for s in sidecar] for x in ["json", "exiftool"]):
|
||||
click.echo(
|
||||
@@ -1599,7 +1628,7 @@ def export(
|
||||
),
|
||||
err=True,
|
||||
)
|
||||
raise click.Abort()
|
||||
sys.exit(1)
|
||||
|
||||
if xattr_template:
|
||||
for attr, _ in xattr_template:
|
||||
@@ -1612,7 +1641,7 @@ def export(
|
||||
),
|
||||
err=True,
|
||||
)
|
||||
raise click.Abort()
|
||||
sys.exit(1)
|
||||
|
||||
if save_config:
|
||||
verbose_(f"Saving options to file {save_config}")
|
||||
@@ -1633,7 +1662,7 @@ def export(
|
||||
click.echo(
|
||||
click.style(f"DEST {dest} must be valid path", fg=CLI_COLOR_ERROR), err=True
|
||||
)
|
||||
raise click.Abort()
|
||||
sys.exit(1)
|
||||
|
||||
dest = str(pathlib.Path(dest).resolve())
|
||||
|
||||
@@ -1644,7 +1673,7 @@ def export(
|
||||
),
|
||||
err=True,
|
||||
)
|
||||
raise click.Abort()
|
||||
sys.exit(1)
|
||||
|
||||
# if use_photokit and not check_photokit_authorization():
|
||||
# click.echo(
|
||||
@@ -3148,6 +3177,9 @@ def export_photo_to_directory(
|
||||
f"Retrying export for photo ({photo.uuid}: {photo.original_filename})"
|
||||
)
|
||||
except Exception as e:
|
||||
if DEBUG:
|
||||
# if debug mode, don't swallow the exceptions
|
||||
raise e
|
||||
click.echo(
|
||||
click.style(
|
||||
f"Error exporting photo ({photo.uuid}: {photo.original_filename}) as {filename}: {e}",
|
||||
@@ -3516,7 +3548,7 @@ def write_export_report(report_file, results):
|
||||
click.style("Could not open output file for writing", fg=CLI_COLOR_ERROR),
|
||||
err=True,
|
||||
)
|
||||
raise click.Abort()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def cleanup_files(dest_path, files_to_keep, fileutil):
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import logging
|
||||
|
||||
from .._constants import _DB_TABLE_NAMES, _PHOTOS_4_VERSION
|
||||
from ..utils import _db_is_locked, _debug, _open_sql_file
|
||||
from ..utils import _db_is_locked, _open_sql_file
|
||||
from .photosdb_utils import get_db_version
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import uuid as uuidlib
|
||||
from pprint import pformat
|
||||
|
||||
from .._constants import _PHOTOS_4_VERSION, SEARCH_CATEGORY_LABEL
|
||||
from ..utils import _db_is_locked, _debug, _open_sql_file, normalize_unicode
|
||||
from ..utils import _db_is_locked, _open_sql_file, normalize_unicode
|
||||
|
||||
"""
|
||||
This module should be imported in the class defintion of PhotosDB in photosdb.py
|
||||
@@ -139,17 +139,6 @@ def _process_searchinfo(self):
|
||||
_db_searchinfo_labels[label] = [uuid]
|
||||
_db_searchinfo_labels_normalized[label_norm] = [uuid]
|
||||
|
||||
if _debug():
|
||||
logging.debug(
|
||||
"_db_searchinfo_categories: \n" + pformat(self._db_searchinfo_categories)
|
||||
)
|
||||
logging.debug("_db_searchinfo_uuid: \n" + pformat(self._db_searchinfo_uuid))
|
||||
logging.debug("_db_searchinfo_labels: \n" + pformat(self._db_searchinfo_labels))
|
||||
logging.debug(
|
||||
"_db_searchinfo_labels_normalized: \n"
|
||||
+ pformat(self._db_searchinfo_labels_normalized)
|
||||
)
|
||||
|
||||
conn.close()
|
||||
|
||||
|
||||
|
||||
@@ -2456,7 +2456,6 @@ class PhotosDB:
|
||||
verbose("Processing moments.")
|
||||
self._process_moments()
|
||||
|
||||
# done processing, dump debug data if requested
|
||||
verbose("Done processing details from Photos library.")
|
||||
|
||||
def _process_moments(self):
|
||||
|
||||
@@ -3883,8 +3883,8 @@ def test_export_directory_template_3():
|
||||
"{created.year}/{foo}",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 2
|
||||
assert "Error: Invalid template" in result.output
|
||||
assert result.exit_code != 0
|
||||
assert "Invalid template" in result.output
|
||||
|
||||
|
||||
def test_export_directory_template_album_1():
|
||||
@@ -4203,8 +4203,8 @@ def test_export_filename_template_3():
|
||||
"{foo}-{original_filename}",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 2
|
||||
assert "Error: Invalid template" in result.output
|
||||
assert result.exit_code != 0
|
||||
assert "Invalid template" in result.output
|
||||
|
||||
|
||||
def test_export_album():
|
||||
@@ -4896,6 +4896,7 @@ def test_export_force_update():
|
||||
in result.output
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
"OSXPHOTOS_TEST_EXPORT" not in os.environ,
|
||||
reason="Skip if not running on author's personal library.",
|
||||
@@ -6073,7 +6074,7 @@ def test_export_report_not_a_file():
|
||||
export, [os.path.join(cwd, CLI_PHOTOS_DB), ".", "-V", "--report", "."]
|
||||
)
|
||||
assert result.exit_code != 0
|
||||
assert "Aborted!" in result.output
|
||||
assert "report is a directory, must be file name" in result.output
|
||||
|
||||
|
||||
def test_export_as_hardlink_download_missing():
|
||||
@@ -6101,7 +6102,7 @@ def test_export_as_hardlink_download_missing():
|
||||
],
|
||||
)
|
||||
assert result.exit_code != 0
|
||||
assert "Aborted!" in result.output
|
||||
assert "Incompatible export options" in result.output
|
||||
|
||||
|
||||
def test_export_missing():
|
||||
@@ -6149,7 +6150,7 @@ def test_export_missing_not_download_missing():
|
||||
export, [os.path.join(cwd, CLI_PHOTOS_DB), ".", "-V", "--missing", "."]
|
||||
)
|
||||
assert result.exit_code != 0
|
||||
assert "Aborted!" in result.output
|
||||
assert "Incompatible export options" in result.output
|
||||
|
||||
|
||||
def test_export_cleanup():
|
||||
@@ -7466,7 +7467,7 @@ def test_bad_query_eval():
|
||||
],
|
||||
)
|
||||
assert result.exit_code != 0
|
||||
assert "Error: Invalid query-eval CRITERIA" in result.output
|
||||
assert "Invalid query-eval CRITERIA" in result.output
|
||||
|
||||
|
||||
def test_query_min_size_1():
|
||||
|
||||
Reference in New Issue
Block a user