Added --debug and crash reporter to export, #628

This commit is contained in:
Rhet Turnbull
2022-02-13 14:51:31 -08:00
parent 65d51ab129
commit 060729c4c4
5 changed files with 51 additions and 30 deletions

View File

@@ -61,6 +61,7 @@ from .configoptions import (
ConfigOptionsInvalidError, ConfigOptionsInvalidError,
ConfigOptionsLoadError, ConfigOptionsLoadError,
) )
from .crash_reporter import crash_reporter
from .datetime_formatter import DateTimeFormatter from .datetime_formatter import DateTimeFormatter
from .exiftool import get_exiftool_path from .exiftool import get_exiftool_path
from .export_db import ExportDB, ExportDBInMemory from .export_db import ExportDB, ExportDBInMemory
@@ -135,12 +136,19 @@ __all__ = [
VERBOSE = False VERBOSE = False
VERBOSE_TIMESTAMP = False VERBOSE_TIMESTAMP = False
# global variable to control debug output
# set via --debug
DEBUG = False
# used to show/hide hidden commands # used to show/hide hidden commands
OSXPHOTOS_HIDDEN = not bool(os.getenv("OSXPHOTOS_SHOW_HIDDEN", default=False)) OSXPHOTOS_HIDDEN = not bool(os.getenv("OSXPHOTOS_SHOW_HIDDEN", default=False))
# used by snap and diff commands # used by snap and diff commands
OSXPHOTOS_SNAPSHOT_DIR = "/private/tmp/osxphotos_snapshots" 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() rich.traceback.install()
@@ -674,7 +682,7 @@ def QUERY_OPTIONS(f):
@click.version_option(__version__, "--version", "-v") @click.version_option(__version__, "--version", "-v")
@click.pass_context @click.pass_context
def cli(ctx, db, json_, debug): 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) @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}. " f"Can be specified multiple times. Valid options are: {PROFILE_SORT_KEYS}. "
"Default = 'cumulative'.", "Default = 'cumulative'.",
) )
@click.option(
"--debug",
required=False,
is_flag=True,
default=False,
hidden=OSXPHOTOS_HIDDEN,
help="Enable debug output.",
)
@DB_ARGUMENT @DB_ARGUMENT
@click.argument("dest", nargs=1, type=click.Path(exists=True)) @click.argument("dest", nargs=1, type=click.Path(exists=True))
@click.pass_obj @click.pass_obj
@click.pass_context @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( def export(
ctx, ctx,
cli_obj, cli_obj,
@@ -1347,6 +1370,7 @@ def export(
preview_if_missing, preview_if_missing,
profile, profile,
profile_sort, profile_sort,
debug,
): ):
"""Export photos from the Photos database. """Export photos from the Photos database.
Export path DEST is required. Export path DEST is required.
@@ -1360,6 +1384,11 @@ def export(
to modify this behavior. to modify this behavior.
""" """
global DEBUG
if debug:
DEBUG = True
osxphotos._set_debug(True)
if profile: if profile:
click.echo("Profiling...") click.echo("Profiling...")
profile_sort = profile_sort or ["cumulative"] profile_sort = profile_sort or ["cumulative"]
@@ -1403,7 +1432,7 @@ def export(
), ),
err=True, err=True,
) )
raise click.Abort() sys.exit(1)
# re-set the local vars to the corresponding config value # 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 # 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, err=True,
) )
raise click.Abort() sys.exit(1)
if all(x in [s.lower() for s in sidecar] for x in ["json", "exiftool"]): if all(x in [s.lower() for s in sidecar] for x in ["json", "exiftool"]):
click.echo( click.echo(
@@ -1599,7 +1628,7 @@ def export(
), ),
err=True, err=True,
) )
raise click.Abort() sys.exit(1)
if xattr_template: if xattr_template:
for attr, _ in xattr_template: for attr, _ in xattr_template:
@@ -1612,7 +1641,7 @@ def export(
), ),
err=True, err=True,
) )
raise click.Abort() sys.exit(1)
if save_config: if save_config:
verbose_(f"Saving options to file {save_config}") verbose_(f"Saving options to file {save_config}")
@@ -1633,7 +1662,7 @@ def export(
click.echo( click.echo(
click.style(f"DEST {dest} must be valid path", fg=CLI_COLOR_ERROR), err=True 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()) dest = str(pathlib.Path(dest).resolve())
@@ -1644,7 +1673,7 @@ def export(
), ),
err=True, err=True,
) )
raise click.Abort() sys.exit(1)
# if use_photokit and not check_photokit_authorization(): # if use_photokit and not check_photokit_authorization():
# click.echo( # click.echo(
@@ -3148,6 +3177,9 @@ def export_photo_to_directory(
f"Retrying export for photo ({photo.uuid}: {photo.original_filename})" f"Retrying export for photo ({photo.uuid}: {photo.original_filename})"
) )
except Exception as e: except Exception as e:
if DEBUG:
# if debug mode, don't swallow the exceptions
raise e
click.echo( click.echo(
click.style( click.style(
f"Error exporting photo ({photo.uuid}: {photo.original_filename}) as {filename}: {e}", 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), click.style("Could not open output file for writing", fg=CLI_COLOR_ERROR),
err=True, err=True,
) )
raise click.Abort() sys.exit(1)
def cleanup_files(dest_path, files_to_keep, fileutil): def cleanup_files(dest_path, files_to_keep, fileutil):

View File

@@ -4,7 +4,7 @@
import logging import logging
from .._constants import _DB_TABLE_NAMES, _PHOTOS_4_VERSION 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 from .photosdb_utils import get_db_version

View File

@@ -10,7 +10,7 @@ import uuid as uuidlib
from pprint import pformat from pprint import pformat
from .._constants import _PHOTOS_4_VERSION, SEARCH_CATEGORY_LABEL 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 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[label] = [uuid]
_db_searchinfo_labels_normalized[label_norm] = [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() conn.close()

View File

@@ -2456,7 +2456,6 @@ class PhotosDB:
verbose("Processing moments.") verbose("Processing moments.")
self._process_moments() self._process_moments()
# done processing, dump debug data if requested
verbose("Done processing details from Photos library.") verbose("Done processing details from Photos library.")
def _process_moments(self): def _process_moments(self):

View File

@@ -3883,8 +3883,8 @@ def test_export_directory_template_3():
"{created.year}/{foo}", "{created.year}/{foo}",
], ],
) )
assert result.exit_code == 2 assert result.exit_code != 0
assert "Error: Invalid template" in result.output assert "Invalid template" in result.output
def test_export_directory_template_album_1(): def test_export_directory_template_album_1():
@@ -4203,8 +4203,8 @@ def test_export_filename_template_3():
"{foo}-{original_filename}", "{foo}-{original_filename}",
], ],
) )
assert result.exit_code == 2 assert result.exit_code != 0
assert "Error: Invalid template" in result.output assert "Invalid template" in result.output
def test_export_album(): def test_export_album():
@@ -4896,6 +4896,7 @@ def test_export_force_update():
in result.output in result.output
) )
@pytest.mark.skipif( @pytest.mark.skipif(
"OSXPHOTOS_TEST_EXPORT" not in os.environ, "OSXPHOTOS_TEST_EXPORT" not in os.environ,
reason="Skip if not running on author's personal library.", 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", "."] export, [os.path.join(cwd, CLI_PHOTOS_DB), ".", "-V", "--report", "."]
) )
assert result.exit_code != 0 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(): def test_export_as_hardlink_download_missing():
@@ -6101,7 +6102,7 @@ def test_export_as_hardlink_download_missing():
], ],
) )
assert result.exit_code != 0 assert result.exit_code != 0
assert "Aborted!" in result.output assert "Incompatible export options" in result.output
def test_export_missing(): 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", "."] export, [os.path.join(cwd, CLI_PHOTOS_DB), ".", "-V", "--missing", "."]
) )
assert result.exit_code != 0 assert result.exit_code != 0
assert "Aborted!" in result.output assert "Incompatible export options" in result.output
def test_export_cleanup(): def test_export_cleanup():
@@ -7466,7 +7467,7 @@ def test_bad_query_eval():
], ],
) )
assert result.exit_code != 0 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(): def test_query_min_size_1():